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

rong 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 487cc2d84e [IOTDB-3145] Support data type inferring in Expressions 
(#5900)
487cc2d84e is described below

commit 487cc2d84e8b1848f694ff6d99ca33ec4921f41f
Author: Steve Yurong Su <[email protected]>
AuthorDate: Sun May 15 00:16:19 2022 +0800

    [IOTDB-3145] Support data type inferring in Expressions (#5900)
    
    Support data type inferring in Expressions
    Support comparing BOOLEAN and TEXT
---
 .../iotdb/db/integration/IoTDBArithmeticIT.java    |  2 +-
 .../iotdb/db/mpp/plan/analyze/TypeProvider.java    |  4 +
 .../iotdb/db/query/expression/Expression.java      | 35 ++++++---
 .../expression/binary/AdditionExpression.java      |  2 +-
 .../binary/ArithmeticBinaryExpression.java         | 60 +++++++++++++++
 .../expression/binary/CompareBinaryExpression.java | 85 ++++++++++++++++++++++
 .../expression/binary/DivisionExpression.java      |  2 +-
 .../query/expression/binary/EqualToExpression.java |  2 +-
 .../expression/binary/GreaterEqualExpression.java  |  2 +-
 .../expression/binary/GreaterThanExpression.java   |  2 +-
 .../expression/binary/LessEqualExpression.java     |  2 +-
 .../expression/binary/LessThanExpression.java      |  2 +-
 .../expression/binary/LogicAndExpression.java      |  2 +-
 ...rExpression.java => LogicBinaryExpression.java} | 35 ++++-----
 .../query/expression/binary/LogicOrExpression.java |  2 +-
 .../query/expression/binary/ModuloExpression.java  |  2 +-
 .../binary/MultiplicationExpression.java           |  2 +-
 .../expression/binary/NonEqualExpression.java      |  2 +-
 .../expression/binary/SubtractionExpression.java   |  2 +-
 .../db/query/expression/leaf/ConstantOperand.java  |  7 ++
 .../query/expression/leaf/TimeSeriesOperand.java   |  7 ++
 .../db/query/expression/leaf/TimestampOperand.java |  7 ++
 .../query/expression/multi/FunctionExpression.java | 33 +++++++++
 .../db/query/expression/unary/InExpression.java    | 11 +++
 .../db/query/expression/unary/LikeExpression.java  | 14 ++++
 .../query/expression/unary/LogicNotExpression.java | 14 ++++
 .../query/expression/unary/NegationExpression.java | 20 +++++
 .../query/expression/unary/RegularExpression.java  | 14 ++++
 .../api/customizer/parameter/UDFParameters.java    | 12 +++
 .../query/udf/core/executor/UDTFTypeInferrer.java  | 68 +++++++++++++++++
 .../binary/ArithmeticBinaryTransformer.java        |  9 ++-
 .../binary/CompareBinaryTransformer.java           | 60 ++++++++++++---
 .../binary/CompareEqualToTransformer.java          | 27 +++----
 .../binary/CompareGreaterEqualTransformer.java     | 17 ++++-
 .../binary/CompareGreaterThanTransformer.java      | 17 ++++-
 .../binary/CompareLessEqualTransformer.java        | 17 ++++-
 .../binary/CompareLessThanTransformer.java         | 17 ++++-
 .../binary/CompareNonEqualTransformer.java         | 26 +++----
 .../transformer/binary/LogicBinaryTransformer.java | 10 +--
 39 files changed, 552 insertions(+), 102 deletions(-)

diff --git 
a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBArithmeticIT.java
 
b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBArithmeticIT.java
index 709494a978..f82d9ccb47 100644
--- 
a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBArithmeticIT.java
+++ 
b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBArithmeticIT.java
@@ -281,7 +281,7 @@ public class IoTDBArithmeticIT {
         Statement statement = connection.createStatement()) {
       statement.executeQuery("select s1 + s6 from root.sg.d1");
     } catch (SQLException throwable) {
-      assertTrue(throwable.getMessage().contains("Unsupported data type: 
TEXT"));
+      assertTrue(throwable.getMessage().contains("Unsupported dataType: 
TEXT"));
     }
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/TypeProvider.java 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/TypeProvider.java
index 34d8acfc9a..6c70c44e2d 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/TypeProvider.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/TypeProvider.java
@@ -55,6 +55,10 @@ public class TypeProvider {
     this.typeMap.put(path, dataType);
   }
 
+  public boolean containsTypeInfoOf(String path) {
+    return typeMap.containsKey(path);
+  }
+
   public void serialize(ByteBuffer byteBuffer) {
     ReadWriteIOUtils.write(typeMap.size(), byteBuffer);
     for (Map.Entry<String, TSDataType> entry : typeMap.entrySet()) {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/Expression.java 
b/server/src/main/java/org/apache/iotdb/db/query/expression/Expression.java
index 14d5007739..4dceb6106e 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/expression/Expression.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/expression/Expression.java
@@ -22,6 +22,8 @@ package org.apache.iotdb.db.query.expression;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.db.query.expression.binary.AdditionExpression;
 import org.apache.iotdb.db.query.expression.binary.DivisionExpression;
@@ -56,6 +58,7 @@ import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.time.ZoneId;
+import java.util.Arrays;
 import java.util.Deque;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -108,6 +111,24 @@ public abstract class Expression {
   public abstract void constructUdfExecutors(
       Map<String, UDTFExecutor> expressionName2Executor, ZoneId zoneId);
 
+  
/////////////////////////////////////////////////////////////////////////////////////////////////
+  // type inference
+  
/////////////////////////////////////////////////////////////////////////////////////////////////
+  public abstract TSDataType inferTypes(TypeProvider typeProvider);
+
+  protected static void checkInputExpressionDataType(
+      String expressionString, TSDataType actual, TSDataType... expected) {
+    for (TSDataType type : expected) {
+      if (actual.equals(type)) {
+        return;
+      }
+    }
+    throw new SemanticException(
+        String.format(
+            "Invalid input expression data type. expression: %s, actual data 
type: %s, expected data type(s): %s.",
+            expressionString, actual.name(), Arrays.toString(expected)));
+  }
+
   
/////////////////////////////////////////////////////////////////////////////////////////////////
   // For expression evaluation DAG building
   
/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -127,15 +148,6 @@ public abstract class Expression {
       LayerMemoryAssigner memoryAssigner)
       throws QueryProcessException, IOException;
 
-  
/////////////////////////////////////////////////////////////////////////////////////////////////
-  // getExpressions: returning DIRECT children expressions
-  
/////////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * returns the DIRECT children expressions if it has any, otherwise an EMPTY 
list will be returned
-   */
-  public abstract List<Expression> getExpressions();
-
   
/////////////////////////////////////////////////////////////////////////////////////////////////
   // isConstantOperand
   
/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -246,6 +258,11 @@ public abstract class Expression {
     }
   }
 
+  /**
+   * returns the DIRECT children expressions if it has any, otherwise an EMPTY 
list will be returned
+   */
+  public abstract List<Expression> getExpressions();
+
   
/////////////////////////////////////////////////////////////////////////////////////////////////
   // serialize & deserialize
   
/////////////////////////////////////////////////////////////////////////////////////////////////
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/AdditionExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/AdditionExpression.java
index 6ec5ce8399..6fd5e698fc 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/AdditionExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/AdditionExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticBinaryTra
 
 import java.nio.ByteBuffer;
 
-public class AdditionExpression extends BinaryExpression {
+public class AdditionExpression extends ArithmeticBinaryExpression {
 
   public AdditionExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ArithmeticBinaryExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ArithmeticBinaryExpression.java
new file mode 100644
index 0000000000..185a8ce617
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ArithmeticBinaryExpression.java
@@ -0,0 +1,60 @@
+/*
+ * 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.query.expression.binary;
+
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
+import org.apache.iotdb.db.query.expression.Expression;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import java.nio.ByteBuffer;
+
+public abstract class ArithmeticBinaryExpression extends BinaryExpression {
+
+  protected ArithmeticBinaryExpression(Expression leftExpression, Expression 
rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  protected ArithmeticBinaryExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  @Override
+  public final TSDataType inferTypes(TypeProvider typeProvider) {
+    final String expressionString = toString();
+    if (!typeProvider.containsTypeInfoOf(expressionString)) {
+      checkInputExpressionDataType(
+          leftExpression.toString(),
+          leftExpression.inferTypes(typeProvider),
+          TSDataType.INT32,
+          TSDataType.INT64,
+          TSDataType.FLOAT,
+          TSDataType.DOUBLE);
+      checkInputExpressionDataType(
+          rightExpression.toString(),
+          rightExpression.inferTypes(typeProvider),
+          TSDataType.INT32,
+          TSDataType.INT64,
+          TSDataType.FLOAT,
+          TSDataType.DOUBLE);
+      typeProvider.setType(expressionString, TSDataType.DOUBLE);
+    }
+    return TSDataType.DOUBLE;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/CompareBinaryExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/CompareBinaryExpression.java
new file mode 100644
index 0000000000..66f795faa1
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/CompareBinaryExpression.java
@@ -0,0 +1,85 @@
+/*
+ * 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.query.expression.binary;
+
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
+import org.apache.iotdb.db.query.expression.Expression;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import java.nio.ByteBuffer;
+
+public abstract class CompareBinaryExpression extends BinaryExpression {
+
+  protected CompareBinaryExpression(Expression leftExpression, Expression 
rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  protected CompareBinaryExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) {
+    final String expressionString = toString();
+
+    if (!typeProvider.containsTypeInfoOf(expressionString)) {
+      final TSDataType leftExpressionDataType = 
leftExpression.inferTypes(typeProvider);
+      final TSDataType rightExpressionDataType = 
rightExpression.inferTypes(typeProvider);
+
+      if (!leftExpressionDataType.equals(rightExpressionDataType)) {
+        final String leftExpressionString = leftExpression.toString();
+        final String rightExpressionString = rightExpression.toString();
+
+        if (TSDataType.BOOLEAN.equals(leftExpressionDataType)
+            || TSDataType.BOOLEAN.equals(rightExpressionDataType)) {
+          checkInputExpressionDataType(
+              leftExpressionString, leftExpressionDataType, 
TSDataType.BOOLEAN);
+          checkInputExpressionDataType(
+              rightExpressionString, rightExpressionDataType, 
TSDataType.BOOLEAN);
+        } else if (TSDataType.TEXT.equals(leftExpressionDataType)
+            || TSDataType.TEXT.equals(rightExpressionDataType)) {
+          checkInputExpressionDataType(
+              leftExpressionString, leftExpressionDataType, TSDataType.TEXT);
+          checkInputExpressionDataType(
+              rightExpressionString, rightExpressionDataType, TSDataType.TEXT);
+        } else {
+          checkInputExpressionDataType(
+              leftExpressionString,
+              leftExpressionDataType,
+              TSDataType.INT32,
+              TSDataType.INT64,
+              TSDataType.FLOAT,
+              TSDataType.DOUBLE);
+          checkInputExpressionDataType(
+              rightExpressionString,
+              rightExpressionDataType,
+              TSDataType.INT32,
+              TSDataType.INT64,
+              TSDataType.FLOAT,
+              TSDataType.DOUBLE);
+        }
+      }
+
+      typeProvider.setType(expressionString, TSDataType.BOOLEAN);
+    }
+
+    return TSDataType.BOOLEAN;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/DivisionExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/DivisionExpression.java
index 5ba106f459..8eb9308d91 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/DivisionExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/DivisionExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticDivisionT
 
 import java.nio.ByteBuffer;
 
-public class DivisionExpression extends BinaryExpression {
+public class DivisionExpression extends ArithmeticBinaryExpression {
 
   public DivisionExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/EqualToExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/EqualToExpression.java
index aa85becd07..d966284402 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/EqualToExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/EqualToExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.CompareEqualToTrans
 
 import java.nio.ByteBuffer;
 
-public class EqualToExpression extends BinaryExpression {
+public class EqualToExpression extends CompareBinaryExpression {
 
   public EqualToExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterEqualExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterEqualExpression.java
index 0364212ac8..6d06a29284 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterEqualExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterEqualExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.CompareGreaterEqual
 
 import java.nio.ByteBuffer;
 
-public class GreaterEqualExpression extends BinaryExpression {
+public class GreaterEqualExpression extends CompareBinaryExpression {
 
   public GreaterEqualExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterThanExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterThanExpression.java
index 56589b5e10..6a574f68e9 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterThanExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterThanExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.CompareGreaterThanT
 
 import java.nio.ByteBuffer;
 
-public class GreaterThanExpression extends BinaryExpression {
+public class GreaterThanExpression extends CompareBinaryExpression {
 
   public GreaterThanExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessEqualExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessEqualExpression.java
index 599a05f67b..a0fff83b49 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessEqualExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessEqualExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.CompareLessEqualTra
 
 import java.nio.ByteBuffer;
 
-public class LessEqualExpression extends BinaryExpression {
+public class LessEqualExpression extends CompareBinaryExpression {
 
   public LessEqualExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessThanExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessThanExpression.java
index 1852771e8e..8f49780392 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessThanExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessThanExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.CompareLessThanTran
 
 import java.nio.ByteBuffer;
 
-public class LessThanExpression extends BinaryExpression {
+public class LessThanExpression extends CompareBinaryExpression {
 
   public LessThanExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicAndExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicAndExpression.java
index 35f19c258b..26ac76b3c2 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicAndExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicAndExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.LogicBinaryTransfor
 
 import java.nio.ByteBuffer;
 
-public class LogicAndExpression extends BinaryExpression {
+public class LogicAndExpression extends LogicBinaryExpression {
 
   public LogicAndExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicBinaryExpression.java
similarity index 53%
copy from 
server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java
copy to 
server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicBinaryExpression.java
index ee0609ae16..9ad7e20bfa 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicBinaryExpression.java
@@ -19,37 +19,32 @@
 
 package org.apache.iotdb.db.query.expression.binary;
 
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.query.expression.Expression;
-import org.apache.iotdb.db.query.expression.ExpressionType;
-import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader;
-import 
org.apache.iotdb.db.query.udf.core.transformer.binary.LogicBinaryTransformer;
-import 
org.apache.iotdb.db.query.udf.core.transformer.binary.LogicOrTransformer;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 
 import java.nio.ByteBuffer;
 
-public class LogicOrExpression extends BinaryExpression {
+public abstract class LogicBinaryExpression extends BinaryExpression {
 
-  public LogicOrExpression(Expression leftExpression, Expression 
rightExpression) {
+  protected LogicBinaryExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
   }
 
-  public LogicOrExpression(ByteBuffer byteBuffer) {
+  protected LogicBinaryExpression(ByteBuffer byteBuffer) {
     super(byteBuffer);
   }
 
   @Override
-  protected LogicBinaryTransformer constructTransformer(
-      LayerPointReader leftParentLayerPointReader, LayerPointReader 
rightParentLayerPointReader) {
-    return new LogicOrTransformer(leftParentLayerPointReader, 
rightParentLayerPointReader);
-  }
-
-  @Override
-  protected String operator() {
-    return "|";
-  }
-
-  @Override
-  public ExpressionType getExpressionType() {
-    return ExpressionType.LOGIC_OR;
+  public final TSDataType inferTypes(TypeProvider typeProvider) {
+    final String expressionString = toString();
+    if (!typeProvider.containsTypeInfoOf(expressionString)) {
+      checkInputExpressionDataType(
+          leftExpression.toString(), leftExpression.inferTypes(typeProvider), 
TSDataType.BOOLEAN);
+      checkInputExpressionDataType(
+          rightExpression.toString(), 
rightExpression.inferTypes(typeProvider), TSDataType.BOOLEAN);
+      typeProvider.setType(expressionString, TSDataType.BOOLEAN);
+    }
+    return TSDataType.BOOLEAN;
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java
index ee0609ae16..eff1d56357 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.LogicOrTransformer;
 
 import java.nio.ByteBuffer;
 
-public class LogicOrExpression extends BinaryExpression {
+public class LogicOrExpression extends LogicBinaryExpression {
 
   public LogicOrExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ModuloExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ModuloExpression.java
index e43f23f3c5..39f4738aca 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ModuloExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ModuloExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticModuloTra
 
 import java.nio.ByteBuffer;
 
-public class ModuloExpression extends BinaryExpression {
+public class ModuloExpression extends ArithmeticBinaryExpression {
 
   public ModuloExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/MultiplicationExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/MultiplicationExpression.java
index d5b15dc55d..6b72d5a2d2 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/MultiplicationExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/MultiplicationExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticMultiplic
 
 import java.nio.ByteBuffer;
 
-public class MultiplicationExpression extends BinaryExpression {
+public class MultiplicationExpression extends ArithmeticBinaryExpression {
 
   public MultiplicationExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/NonEqualExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/NonEqualExpression.java
index 6c9337fa57..542d4a7c25 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/NonEqualExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/NonEqualExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.CompareNonEqualTran
 
 import java.nio.ByteBuffer;
 
-public class NonEqualExpression extends BinaryExpression {
+public class NonEqualExpression extends CompareBinaryExpression {
 
   public NonEqualExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/SubtractionExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/SubtractionExpression.java
index 3e31ad9039..372d56cc73 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/SubtractionExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/SubtractionExpression.java
@@ -27,7 +27,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticSubtracti
 
 import java.nio.ByteBuffer;
 
-public class SubtractionExpression extends BinaryExpression {
+public class SubtractionExpression extends ArithmeticBinaryExpression {
 
   public SubtractionExpression(Expression leftExpression, Expression 
rightExpression) {
     super(leftExpression, rightExpression);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/ConstantOperand.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/ConstantOperand.java
index d92c8021c3..7acd877fc0 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/ConstantOperand.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/ConstantOperand.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.query.expression.leaf;
 
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.db.query.expression.Expression;
 import org.apache.iotdb.db.query.expression.ExpressionType;
@@ -91,6 +92,12 @@ public class ConstantOperand extends LeafOperand {
     // Do nothing
   }
 
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) {
+    typeProvider.setType(toString(), dataType);
+    return dataType;
+  }
+
   @Override
   public void bindInputLayerColumnIndexWithExpression(UDTFPlan udtfPlan) {
     // Do nothing
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimeSeriesOperand.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimeSeriesOperand.java
index 11a6b72912..5d896a932f 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimeSeriesOperand.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimeSeriesOperand.java
@@ -23,6 +23,7 @@ import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.metadata.path.PathDeserializeUtil;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.db.query.expression.Expression;
 import org.apache.iotdb.db.query.expression.ExpressionType;
@@ -87,6 +88,11 @@ public class TimeSeriesOperand extends LeafOperand {
     pathSet.add(path);
   }
 
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) {
+    return typeProvider.getType(toString());
+  }
+
   @Override
   public void bindInputLayerColumnIndexWithExpression(UDTFPlan udtfPlan) {
     inputColumnIndex = udtfPlan.getReaderIndexByExpressionName(toString());
@@ -125,6 +131,7 @@ public class TimeSeriesOperand extends LeafOperand {
     return expressionIntermediateLayerMap.get(this);
   }
 
+  @Override
   public String getExpressionStringInternal() {
     return path.isMeasurementAliasExists() ? path.getFullPathWithAlias() : 
path.getFullPath();
   }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimestampOperand.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimestampOperand.java
index 73c77a2b37..bb473451b7 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimestampOperand.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimestampOperand.java
@@ -22,6 +22,7 @@ package org.apache.iotdb.db.query.expression.leaf;
 import org.apache.iotdb.commons.path.PartialPath;
 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.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.db.query.expression.Expression;
 import org.apache.iotdb.db.query.expression.ExpressionType;
@@ -75,6 +76,12 @@ public class TimestampOperand extends LeafOperand {
     pathSet.add(TIMESTAMP_PARTIAL_PATH);
   }
 
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) {
+    typeProvider.setType(toString(), TSDataType.INT64);
+    return TSDataType.INT64;
+  }
+
   @Override
   public void bindInputLayerColumnIndexWithExpression(UDTFPlan udtfPlan) {
     // do nothing
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/multi/FunctionExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/multi/FunctionExpression.java
index b2bd93b05c..0ec226403f 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/multi/FunctionExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/multi/FunctionExpression.java
@@ -23,6 +23,8 @@ import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.qp.constant.SQLConstant;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.db.qp.strategy.optimizer.ConcatPathOptimizer;
@@ -32,6 +34,7 @@ import 
org.apache.iotdb.db.query.expression.leaf.TimeSeriesOperand;
 import org.apache.iotdb.db.query.udf.api.customizer.strategy.AccessStrategy;
 import org.apache.iotdb.db.query.udf.core.executor.UDTFContext;
 import org.apache.iotdb.db.query.udf.core.executor.UDTFExecutor;
+import org.apache.iotdb.db.query.udf.core.executor.UDTFTypeInferrer;
 import org.apache.iotdb.db.query.udf.core.layer.IntermediateLayer;
 import org.apache.iotdb.db.query.udf.core.layer.LayerMemoryAssigner;
 import 
org.apache.iotdb.db.query.udf.core.layer.MultiInputColumnIntermediateLayer;
@@ -43,6 +46,7 @@ import 
org.apache.iotdb.db.query.udf.core.transformer.multi.UDFQueryRowTransform
 import 
org.apache.iotdb.db.query.udf.core.transformer.multi.UDFQueryRowWindowTransformer;
 import 
org.apache.iotdb.db.query.udf.core.transformer.multi.UDFQueryTransformer;
 import 
org.apache.iotdb.db.query.udf.core.transformer.unary.TransparentTransformer;
+import org.apache.iotdb.db.utils.TypeInferenceUtils;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
@@ -238,6 +242,35 @@ public class FunctionExpression extends Expression {
     expressionName2Executor.put(expressionString, new UDTFExecutor(this, 
zoneId));
   }
 
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) {
+    final String expressionString = toString();
+
+    if (!typeProvider.containsTypeInfoOf(expressionString)) {
+      for (Expression expression : expressions) {
+        expression.inferTypes(typeProvider);
+      }
+
+      if (isTimeSeriesGeneratingFunctionExpression()) {
+        typeProvider.setType(
+            expressionString, new 
UDTFTypeInferrer(this).inferOutputType(typeProvider));
+      } else {
+        if (expressions.size() != 1) {
+          throw new SemanticException(
+              String.format(
+                  "Builtin aggregation function only accepts 1 input 
expression. Actual %d input expressions.",
+                  expressions.size()));
+        }
+        typeProvider.setType(
+            expressionString,
+            TypeInferenceUtils.getAggrDataType(
+                functionName, 
typeProvider.getType(expressions.get(0).toString())));
+      }
+    }
+
+    return typeProvider.getType(expressionString);
+  }
+
   @Override
   public void bindInputLayerColumnIndexWithExpression(UDTFPlan udtfPlan) {
     for (Expression expression : expressions) {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/InExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/InExpression.java
index 9f329b3728..979d4c2bbc 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/InExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/InExpression.java
@@ -19,11 +19,13 @@
 
 package org.apache.iotdb.db.query.expression.unary;
 
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.query.expression.Expression;
 import org.apache.iotdb.db.query.expression.ExpressionType;
 import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader;
 import org.apache.iotdb.db.query.udf.core.transformer.Transformer;
 import org.apache.iotdb.db.query.udf.core.transformer.unary.InTransformer;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import java.nio.ByteBuffer;
@@ -59,6 +61,15 @@ public class InExpression extends UnaryExpression {
     return values;
   }
 
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) {
+    final String expressionString = toString();
+    if (!typeProvider.containsTypeInfoOf(expressionString)) {
+      typeProvider.setType(expressionString, 
expression.inferTypes(typeProvider));
+    }
+    return typeProvider.getType(expressionString);
+  }
+
   @Override
   protected String getExpressionStringInternal() {
     StringBuilder valuesStringBuilder = new StringBuilder();
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LikeExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LikeExpression.java
index 2d91ac0720..0e94037e72 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LikeExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LikeExpression.java
@@ -19,11 +19,14 @@
 
 package org.apache.iotdb.db.query.expression.unary;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.query.expression.Expression;
 import org.apache.iotdb.db.query.expression.ExpressionType;
 import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader;
 import org.apache.iotdb.db.query.udf.core.transformer.Transformer;
 import org.apache.iotdb.db.query.udf.core.transformer.unary.RegularTransformer;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import java.nio.ByteBuffer;
@@ -115,6 +118,17 @@ public class LikeExpression extends UnaryExpression {
     return stringBuilder.toString();
   }
 
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) throws 
SemanticException {
+    final String expressionString = toString();
+    if (!typeProvider.containsTypeInfoOf(expressionString)) {
+      checkInputExpressionDataType(
+          expression.toString(), expression.inferTypes(typeProvider), 
TSDataType.TEXT);
+      typeProvider.setType(expressionString, TSDataType.TEXT);
+    }
+    return TSDataType.TEXT;
+  }
+
   @Override
   protected String getExpressionStringInternal() {
     return expression + " LIKE '" + pattern + "'";
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LogicNotExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LogicNotExpression.java
index 2c22a52841..a538e4a028 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LogicNotExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LogicNotExpression.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.db.query.expression.unary;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.query.expression.Expression;
 import org.apache.iotdb.db.query.expression.ExpressionType;
 import org.apache.iotdb.db.query.expression.leaf.ConstantOperand;
@@ -27,6 +29,7 @@ import 
org.apache.iotdb.db.query.expression.multi.FunctionExpression;
 import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader;
 import org.apache.iotdb.db.query.udf.core.transformer.Transformer;
 import 
org.apache.iotdb.db.query.udf.core.transformer.unary.LogicNotTransformer;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 
 import java.nio.ByteBuffer;
 
@@ -50,6 +53,17 @@ public class LogicNotExpression extends UnaryExpression {
     return new LogicNotExpression(childExpression);
   }
 
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) throws 
SemanticException {
+    final String expressionString = toString();
+    if (!typeProvider.containsTypeInfoOf(expressionString)) {
+      checkInputExpressionDataType(
+          expression.toString(), expression.inferTypes(typeProvider), 
TSDataType.BOOLEAN);
+      typeProvider.setType(expressionString, TSDataType.BOOLEAN);
+    }
+    return TSDataType.BOOLEAN;
+  }
+
   @Override
   public String getExpressionStringInternal() {
     return expression instanceof FunctionExpression
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/NegationExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/NegationExpression.java
index 8e12a85a57..6d8c111078 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/NegationExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/NegationExpression.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.db.query.expression.unary;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.query.expression.Expression;
 import org.apache.iotdb.db.query.expression.ExpressionType;
 import org.apache.iotdb.db.query.expression.leaf.ConstantOperand;
@@ -27,6 +29,7 @@ import 
org.apache.iotdb.db.query.expression.multi.FunctionExpression;
 import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader;
 import org.apache.iotdb.db.query.udf.core.transformer.Transformer;
 import 
org.apache.iotdb.db.query.udf.core.transformer.unary.ArithmeticNegationTransformer;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 
 import java.nio.ByteBuffer;
 
@@ -50,6 +53,23 @@ public class NegationExpression extends UnaryExpression {
     return new NegationExpression(childExpression);
   }
 
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) throws 
SemanticException {
+    final String expressionString = toString();
+    if (!typeProvider.containsTypeInfoOf(expressionString)) {
+      TSDataType inputExpressionType = expression.inferTypes(typeProvider);
+      checkInputExpressionDataType(
+          expression.toString(),
+          inputExpressionType,
+          TSDataType.INT32,
+          TSDataType.INT64,
+          TSDataType.FLOAT,
+          TSDataType.DOUBLE);
+      typeProvider.setType(expressionString, inputExpressionType);
+    }
+    return typeProvider.getType(expressionString);
+  }
+
   @Override
   public String getExpressionStringInternal() {
     return expression instanceof TimeSeriesOperand
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/RegularExpression.java
 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/RegularExpression.java
index f6027a9c8e..a8b30f0d5a 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/RegularExpression.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/RegularExpression.java
@@ -19,11 +19,14 @@
 
 package org.apache.iotdb.db.query.expression.unary;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.query.expression.Expression;
 import org.apache.iotdb.db.query.expression.ExpressionType;
 import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader;
 import org.apache.iotdb.db.query.udf.core.transformer.Transformer;
 import org.apache.iotdb.db.query.udf.core.transformer.unary.RegularTransformer;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import org.apache.commons.lang3.Validate;
@@ -72,6 +75,17 @@ public class RegularExpression extends UnaryExpression {
     return new RegularExpression(childExpression, patternString, pattern);
   }
 
+  @Override
+  public TSDataType inferTypes(TypeProvider typeProvider) throws 
SemanticException {
+    final String expressionString = toString();
+    if (!typeProvider.containsTypeInfoOf(expressionString)) {
+      checkInputExpressionDataType(
+          expression.toString(), expression.inferTypes(typeProvider), 
TSDataType.TEXT);
+      typeProvider.setType(expressionString, TSDataType.TEXT);
+    }
+    return TSDataType.TEXT;
+  }
+
   @Override
   protected String getExpressionStringInternal() {
     return expression + " REGEXP '" + patternString + "'";
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/api/customizer/parameter/UDFParameters.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/api/customizer/parameter/UDFParameters.java
index 5f057ccf8d..9b9b6640f0 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/api/customizer/parameter/UDFParameters.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/api/customizer/parameter/UDFParameters.java
@@ -22,6 +22,7 @@ package 
org.apache.iotdb.db.query.udf.api.customizer.parameter;
 import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.query.expression.Expression;
 import org.apache.iotdb.db.query.expression.multi.FunctionExpression;
 import org.apache.iotdb.db.query.udf.api.UDTF;
@@ -63,6 +64,17 @@ public class UDFParameters {
     }
   }
 
+  public UDFParameters(FunctionExpression functionExpression, TypeProvider 
typeProvider)
+      throws QueryProcessException {
+    expressions = functionExpression.getExpressions();
+    paths = functionExpression.getPaths();
+    attributes = functionExpression.getFunctionAttributes();
+    dataTypes = new ArrayList<>();
+    for (Expression expression : expressions) {
+      dataTypes.add(typeProvider.getType(expression.toString()));
+    }
+  }
+
   public List<Expression> getExpressions() {
     return expressions;
   }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/executor/UDTFTypeInferrer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/executor/UDTFTypeInferrer.java
new file mode 100644
index 0000000000..ca7233906a
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/executor/UDTFTypeInferrer.java
@@ -0,0 +1,68 @@
+/*
+ * 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.query.udf.core.executor;
+
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
+import org.apache.iotdb.db.query.expression.multi.FunctionExpression;
+import org.apache.iotdb.db.query.udf.api.UDTF;
+import org.apache.iotdb.db.query.udf.api.customizer.config.UDTFConfigurations;
+import 
org.apache.iotdb.db.query.udf.api.customizer.parameter.UDFParameterValidator;
+import org.apache.iotdb.db.query.udf.api.customizer.parameter.UDFParameters;
+import org.apache.iotdb.db.query.udf.service.UDFRegistrationService;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.ZoneId;
+
+public class UDTFTypeInferrer {
+
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(UDTFTypeInferrer.class);
+
+  protected final FunctionExpression expression;
+
+  public UDTFTypeInferrer(FunctionExpression expression) {
+    this.expression = expression;
+  }
+
+  public TSDataType inferOutputType(TypeProvider typeProvider) {
+    try {
+      UDTF udtf = (UDTF) 
UDFRegistrationService.getInstance().reflect(expression);
+
+      UDFParameters parameters = new UDFParameters(expression, typeProvider);
+      udtf.validate(new UDFParameterValidator(parameters));
+
+      // use ZoneId.systemDefault() because UDF's data type is ZoneId 
independent
+      UDTFConfigurations configurations = new 
UDTFConfigurations(ZoneId.systemDefault());
+      udtf.beforeStart(parameters, configurations);
+
+      udtf.beforeDestroy();
+
+      return configurations.getOutputDataType();
+    } catch (Exception e) {
+      LOGGER.warn("Error occurred during inferring UDF data type", e);
+      throw new SemanticException(
+          String.format("Error occurred during inferring UDF data type: %s", 
System.lineSeparator())
+              + e);
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/ArithmeticBinaryTransformer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/ArithmeticBinaryTransformer.java
index 29a17a1ee1..751fc534d6 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/ArithmeticBinaryTransformer.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/ArithmeticBinaryTransformer.java
@@ -35,11 +35,12 @@ public abstract class ArithmeticBinaryTransformer extends 
BinaryTransformer {
 
   @Override
   protected void checkType() {
-    if (leftPointReaderDataType == TSDataType.BOOLEAN) {
-      throw new 
UnSupportedDataTypeException(leftPointReader.getDataType().toString());
+    if (leftPointReaderDataType == TSDataType.BOOLEAN
+        || rightPointReaderDataType == TSDataType.BOOLEAN) {
+      throw new UnSupportedDataTypeException(TSDataType.BOOLEAN.name());
     }
-    if (rightPointReaderDataType == TSDataType.BOOLEAN) {
-      throw new 
UnSupportedDataTypeException(rightPointReader.getDataType().toString());
+    if (leftPointReaderDataType == TSDataType.TEXT || rightPointReaderDataType 
== TSDataType.TEXT) {
+      throw new UnSupportedDataTypeException(TSDataType.TEXT.name());
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareBinaryTransformer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareBinaryTransformer.java
index 90f506ddd7..42b42e1058 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareBinaryTransformer.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareBinaryTransformer.java
@@ -25,35 +25,73 @@ import 
org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 
 import java.io.IOException;
+import java.util.Objects;
 
 public abstract class CompareBinaryTransformer extends BinaryTransformer {
 
+  @FunctionalInterface
+  protected interface Evaluator {
+
+    boolean evaluate() throws QueryProcessException, IOException;
+  }
+
+  protected final Evaluator evaluator;
+
   protected CompareBinaryTransformer(
       LayerPointReader leftPointReader, LayerPointReader rightPointReader)
       throws UnSupportedDataTypeException {
     super(leftPointReader, rightPointReader);
+    evaluator =
+        TSDataType.TEXT.equals(leftPointReaderDataType)
+            ? constructTextEvaluator()
+            : constructNumberEvaluator();
+  }
+
+  protected abstract Evaluator constructNumberEvaluator();
+
+  protected abstract Evaluator constructTextEvaluator();
+
+  protected static int compare(CharSequence cs1, CharSequence cs2) {
+    if (Objects.requireNonNull(cs1) == Objects.requireNonNull(cs2)) {
+      return 0;
+    }
+
+    if (cs1.getClass() == cs2.getClass() && cs1 instanceof Comparable) {
+      return ((Comparable<Object>) cs1).compareTo(cs2);
+    }
+
+    for (int i = 0, len = Math.min(cs1.length(), cs2.length()); i < len; i++) {
+      char a = cs1.charAt(i);
+      char b = cs2.charAt(i);
+      if (a != b) {
+        return a - b;
+      }
+    }
+
+    return cs1.length() - cs2.length();
   }
 
   @Override
-  protected void checkType() {
-    if (leftPointReaderDataType == TSDataType.BOOLEAN) {
-      throw new 
UnSupportedDataTypeException(leftPointReader.getDataType().toString());
+  protected final void checkType() {
+    if (leftPointReaderDataType.equals(rightPointReaderDataType)) {
+      return;
+    }
+
+    if (leftPointReaderDataType.equals(TSDataType.BOOLEAN)
+        || rightPointReaderDataType.equals(TSDataType.BOOLEAN)) {
+      throw new UnSupportedDataTypeException(TSDataType.BOOLEAN.toString());
     }
-    if (rightPointReaderDataType == TSDataType.BOOLEAN) {
-      throw new 
UnSupportedDataTypeException(rightPointReader.getDataType().toString());
+    if (leftPointReaderDataType.equals(TSDataType.TEXT)
+        || rightPointReaderDataType.equals(TSDataType.TEXT)) {
+      throw new UnSupportedDataTypeException(TSDataType.TEXT.toString());
     }
   }
 
   @Override
   protected final void transformAndCache() throws QueryProcessException, 
IOException {
-    cachedBoolean =
-        evaluate(
-            castCurrentValueToDoubleOperand(leftPointReader, 
leftPointReaderDataType),
-            castCurrentValueToDoubleOperand(rightPointReader, 
rightPointReaderDataType));
+    cachedBoolean = evaluator.evaluate();
   }
 
-  abstract boolean evaluate(double leftOperand, double rightOperand);
-
   @Override
   public TSDataType getDataType() {
     return TSDataType.BOOLEAN;
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareEqualToTransformer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareEqualToTransformer.java
index 8484df276c..af6b2c8d65 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareEqualToTransformer.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareEqualToTransformer.java
@@ -20,8 +20,6 @@
 package org.apache.iotdb.db.query.udf.core.transformer.binary;
 
 import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader;
-import org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 
 public class CompareEqualToTransformer extends CompareBinaryTransformer {
 
@@ -31,21 +29,20 @@ public class CompareEqualToTransformer extends 
CompareBinaryTransformer {
   }
 
   @Override
-  protected void checkType() {
-    if ((leftPointReaderDataType == TSDataType.BOOLEAN
-            && rightPointReaderDataType != TSDataType.BOOLEAN)
-        || (leftPointReaderDataType != TSDataType.BOOLEAN
-            && rightPointReaderDataType == TSDataType.BOOLEAN)) {
-      throw new UnSupportedDataTypeException(
-          "left: "
-              + leftPointReaderDataType.toString()
-              + ", right: "
-              + rightPointReaderDataType.toString());
-    }
+  protected Evaluator constructNumberEvaluator() {
+    return () ->
+        Double.compare(
+                castCurrentValueToDoubleOperand(leftPointReader, 
leftPointReaderDataType),
+                castCurrentValueToDoubleOperand(rightPointReader, 
rightPointReaderDataType))
+            == 0;
   }
 
   @Override
-  protected boolean evaluate(double leftOperand, double rightOperand) {
-    return Double.compare(leftOperand, rightOperand) == 0;
+  protected Evaluator constructTextEvaluator() {
+    return () ->
+        compare(
+                leftPointReader.currentBinary().getStringValue(),
+                rightPointReader.currentBinary().getStringValue())
+            == 0;
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareGreaterEqualTransformer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareGreaterEqualTransformer.java
index 7854143cff..1e98bfe423 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareGreaterEqualTransformer.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareGreaterEqualTransformer.java
@@ -29,7 +29,20 @@ public class CompareGreaterEqualTransformer extends 
CompareBinaryTransformer {
   }
 
   @Override
-  protected boolean evaluate(double leftOperand, double rightOperand) {
-    return Double.compare(leftOperand, rightOperand) >= 0;
+  protected Evaluator constructNumberEvaluator() {
+    return () ->
+        Double.compare(
+                castCurrentValueToDoubleOperand(leftPointReader, 
leftPointReaderDataType),
+                castCurrentValueToDoubleOperand(rightPointReader, 
rightPointReaderDataType))
+            >= 0;
+  }
+
+  @Override
+  protected Evaluator constructTextEvaluator() {
+    return () ->
+        compare(
+                leftPointReader.currentBinary().getStringValue(),
+                rightPointReader.currentBinary().getStringValue())
+            >= 0;
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareGreaterThanTransformer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareGreaterThanTransformer.java
index 627c4b17bf..9e7a5ea3ba 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareGreaterThanTransformer.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareGreaterThanTransformer.java
@@ -29,7 +29,20 @@ public class CompareGreaterThanTransformer extends 
CompareBinaryTransformer {
   }
 
   @Override
-  protected boolean evaluate(double leftOperand, double rightOperand) {
-    return Double.compare(leftOperand, rightOperand) > 0;
+  protected Evaluator constructNumberEvaluator() {
+    return () ->
+        Double.compare(
+                castCurrentValueToDoubleOperand(leftPointReader, 
leftPointReaderDataType),
+                castCurrentValueToDoubleOperand(rightPointReader, 
rightPointReaderDataType))
+            > 0;
+  }
+
+  @Override
+  protected Evaluator constructTextEvaluator() {
+    return () ->
+        compare(
+                leftPointReader.currentBinary().getStringValue(),
+                rightPointReader.currentBinary().getStringValue())
+            > 0;
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareLessEqualTransformer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareLessEqualTransformer.java
index 2b00dca3fb..0c53e86949 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareLessEqualTransformer.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareLessEqualTransformer.java
@@ -29,7 +29,20 @@ public class CompareLessEqualTransformer extends 
CompareBinaryTransformer {
   }
 
   @Override
-  protected boolean evaluate(double leftOperand, double rightOperand) {
-    return Double.compare(leftOperand, rightOperand) <= 0;
+  protected Evaluator constructNumberEvaluator() {
+    return () ->
+        Double.compare(
+                castCurrentValueToDoubleOperand(leftPointReader, 
leftPointReaderDataType),
+                castCurrentValueToDoubleOperand(rightPointReader, 
rightPointReaderDataType))
+            <= 0;
+  }
+
+  @Override
+  protected Evaluator constructTextEvaluator() {
+    return () ->
+        compare(
+                leftPointReader.currentBinary().getStringValue(),
+                rightPointReader.currentBinary().getStringValue())
+            <= 0;
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareLessThanTransformer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareLessThanTransformer.java
index ea2ebeded5..9e77e2aa21 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareLessThanTransformer.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareLessThanTransformer.java
@@ -29,7 +29,20 @@ public class CompareLessThanTransformer extends 
CompareBinaryTransformer {
   }
 
   @Override
-  protected boolean evaluate(double leftOperand, double rightOperand) {
-    return Double.compare(leftOperand, rightOperand) < 0;
+  protected Evaluator constructNumberEvaluator() {
+    return () ->
+        Double.compare(
+                castCurrentValueToDoubleOperand(leftPointReader, 
leftPointReaderDataType),
+                castCurrentValueToDoubleOperand(rightPointReader, 
rightPointReaderDataType))
+            < 0;
+  }
+
+  @Override
+  protected Evaluator constructTextEvaluator() {
+    return () ->
+        compare(
+                leftPointReader.currentBinary().getStringValue(),
+                rightPointReader.currentBinary().getStringValue())
+            < 0;
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareNonEqualTransformer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareNonEqualTransformer.java
index 795b011bdc..024c54deb5 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareNonEqualTransformer.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/CompareNonEqualTransformer.java
@@ -21,7 +21,6 @@ package org.apache.iotdb.db.query.udf.core.transformer.binary;
 
 import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader;
 import org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 
 public class CompareNonEqualTransformer extends CompareBinaryTransformer {
 
@@ -32,21 +31,20 @@ public class CompareNonEqualTransformer extends 
CompareBinaryTransformer {
   }
 
   @Override
-  protected void checkType() {
-    if ((leftPointReaderDataType == TSDataType.BOOLEAN
-            && rightPointReaderDataType != TSDataType.BOOLEAN)
-        || (leftPointReaderDataType != TSDataType.BOOLEAN
-            && rightPointReaderDataType == TSDataType.BOOLEAN)) {
-      throw new UnSupportedDataTypeException(
-          "left: "
-              + leftPointReaderDataType.toString()
-              + ", right: "
-              + rightPointReaderDataType.toString());
-    }
+  protected Evaluator constructNumberEvaluator() {
+    return () ->
+        Double.compare(
+                castCurrentValueToDoubleOperand(leftPointReader, 
leftPointReaderDataType),
+                castCurrentValueToDoubleOperand(rightPointReader, 
rightPointReaderDataType))
+            != 0;
   }
 
   @Override
-  protected boolean evaluate(double leftOperand, double rightOperand) {
-    return Double.compare(leftOperand, rightOperand) != 0;
+  protected Evaluator constructTextEvaluator() {
+    return () ->
+        compare(
+                leftPointReader.currentBinary().getStringValue(),
+                rightPointReader.currentBinary().getStringValue())
+            != 0;
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/LogicBinaryTransformer.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/LogicBinaryTransformer.java
index d8e1a36012..7eee752775 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/LogicBinaryTransformer.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/core/transformer/binary/LogicBinaryTransformer.java
@@ -35,13 +35,9 @@ public abstract class LogicBinaryTransformer extends 
BinaryTransformer {
 
   @Override
   protected void checkType() {
-    if (leftPointReaderDataType != TSDataType.BOOLEAN) {
-      throw new UnSupportedDataTypeException(
-          "Unsupported data type: " + 
leftPointReader.getDataType().toString());
-    }
-    if (rightPointReaderDataType != TSDataType.BOOLEAN) {
-      throw new UnSupportedDataTypeException(
-          "Unsupported data type: " + 
rightPointReader.getDataType().toString());
+    if (leftPointReaderDataType != TSDataType.BOOLEAN
+        || rightPointReaderDataType != TSDataType.BOOLEAN) {
+      throw new UnSupportedDataTypeException("Unsupported data type: " + 
TSDataType.BOOLEAN);
     }
   }
 

Reply via email to