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

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

commit fca8c61b4b053469ea9a4da903c13f6f7dd1ea6c
Author: JackieTien97 <[email protected]>
AuthorDate: Tue Apr 9 17:18:49 2024 +0800

    Add support for builtin scalar and aggregation function
---
 .../java/org/apache/iotdb/rpc/TSStatusCode.java    |   1 +
 .../relational/analyzer/ExpressionAnalyzer.java    | 277 ++++++++-------------
 .../metadata/BuiltinFunctionResolver.java}         |  20 +-
 .../plan/relational/metadata/Metadata.java         |  15 ++
 .../relational/metadata/TableMetadataImpl.java     | 226 +++++++++++++++++
 .../plan/relational/planner/PlannerContext.java}   |  28 ++-
 .../plan/relational/type/InternalTypeManager.java  |  67 +++++
 .../queryengine/plan/relational/type/TypeId.java   |  66 +++++
 .../plan/relational/type/TypeManager.java}         |  27 +-
 .../relational/type/TypeNotFoundException.java}    |  27 +-
 .../relational/type/TypeSignatureTranslator.java   | 107 ++++++++
 .../binary/CompareBinaryColumnTransformer.java     |   2 +-
 .../ternary/CompareTernaryColumnTransformer.java   |   6 +-
 .../dag/column/unary/InColumnTransformer.java      |   4 +-
 .../dag/column/unary/RegularColumnTransformer.java |   2 +-
 .../scalar/CastFunctionColumnTransformer.java      |  14 +-
 .../plan/relational/analyzer/TestMatadata.java     |  30 +++
 .../iotdb/tsfile/read/common/type/BinaryType.java  |   2 +-
 .../iotdb/tsfile/read/common/type/TypeEnum.java    |   2 +-
 .../iotdb/tsfile/read/common/type/TypeFactory.java |   2 +-
 20 files changed, 674 insertions(+), 251 deletions(-)

diff --git 
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java 
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
index ba6a7f06681..5e7fcb543c6 100644
--- 
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
+++ 
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
@@ -82,6 +82,7 @@ public enum TSStatusCode {
   DATABASE_CONFIG_ERROR(525),
   SCHEMA_QUOTA_EXCEEDED(526),
   MEASUREMENT_ALREADY_EXISTS_IN_TEMPLATE(527),
+  TYPE_NOT_FOUND(528),
 
   // Storage Engine
   SYSTEM_READ_ONLY(600),
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java
index 64bd4a98952..cb76bf10504 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java
@@ -23,13 +23,13 @@ import org.apache.iotdb.db.exception.sql.SemanticException;
 import org.apache.iotdb.db.queryengine.common.SessionInfo;
 import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector;
 import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider;
-import org.apache.iotdb.db.queryengine.plan.relational.function.BoundSignature;
 import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
 import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.OperatorNotFoundException;
 import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
 import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
 import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
+import 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundException;
 import org.apache.iotdb.db.relational.sql.tree.ArithmeticBinaryExpression;
 import org.apache.iotdb.db.relational.sql.tree.ArithmeticUnaryExpression;
 import org.apache.iotdb.db.relational.sql.tree.BetweenPredicate;
@@ -103,6 +103,7 @@ import static java.lang.String.format;
 import static java.util.Collections.unmodifiableMap;
 import static java.util.Collections.unmodifiableSet;
 import static java.util.Objects.requireNonNull;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureTranslator.toTypeSignature;
 import static 
org.apache.iotdb.db.relational.sql.tree.DereferenceExpression.isQualifiedAllFieldsReference;
 import static org.apache.iotdb.tsfile.read.common.type.BinaryType.TEXT;
 import static org.apache.iotdb.tsfile.read.common.type.BooleanType.BOOLEAN;
@@ -145,6 +146,10 @@ public class ExpressionAnalyzer {
 
   private final List<Field> sourceFields = new ArrayList<>();
 
+  // Record fields prefixed with labels in row pattern recognition context
+  private final Map<NodeRef<DereferenceExpression>, LabelPrefixedReference> 
labelDereferences =
+      new LinkedHashMap<>();
+
   private ExpressionAnalyzer(
       Metadata metadata,
       AccessControl accessControl,
@@ -615,10 +620,7 @@ public class ExpressionAnalyzer {
         case PLUS:
           Type type = process(node.getValue(), context);
 
-          if (!type.equals(DOUBLE)
-              && !type.equals(FLOAT)
-              && !type.equals(INT32)
-              && !type.equals(INT64)) {
+          if (!isNumericType(type)) {
             // TODO: figure out a type-agnostic way of dealing with this. 
Maybe add a special unary
             // operator
             // that types can chose to implement, or piggyback on the 
existence of the negation
@@ -731,106 +733,64 @@ public class ExpressionAnalyzer {
     @Override
     protected Type visitFunctionCall(
         FunctionCall node, StackableAstVisitorContext<Context> context) {
-      // TODO implememt function call
-      throw new SemanticException("FunctionCall is not implemented yet.");
-      //      boolean isAggregation = 
functionResolver.isAggregationFunction(session,
-      // node.getName(), accessControl);
-      //      // argument of the form `label.*` is only allowed for row 
pattern count function
-      //      node.getArguments().stream()
-      //          .filter(DereferenceExpression::isQualifiedAllFieldsReference)
-      //          .findAny()
-      //          .ifPresent(allRowsReference -> {
-      //            if (node.getArguments().size() > 1) {
-      //              throw new SemanticException(
-      //                  "label.* syntax is only supported as the only 
argument of row pattern
-      // count function");
-      //            }
-      //          });
-      //
-      //      if (node.isDistinct() && !isAggregation) {
-      //        throw new SemanticException("DISTINCT is not supported for 
non-aggregation
-      // functions");
-      //      }
-      //
-      //      List<TypeSignatureProvider> argumentTypes = 
getCallArgumentTypes(node.getArguments(),
-      // context);
-      //
-      //      ResolvedFunction function;
-      //      try {
-      //        function = functionResolver.resolveFunction(session, 
node.getName(), argumentTypes,
-      // accessControl);
-      //      } catch (TrinoException e) {
-      //        if (e.getLocation().isPresent()) {
-      //          // If analysis of any of the argument types (which is done 
lazily to deal with
-      // lambda
-      //          // expressions) fails, we want to report the original reason 
for the failure
-      //          throw e;
-      //        }
-      //
-      //        // otherwise, it must have failed due to a missing function or 
other reason, so we
-      // report an error at the
-      //        // current location
-      //
-      //        throw new TrinoException(e::getErrorCode, 
extractLocation(node), e.getMessage(), e);
-      //      }
-      //
-      //      if (node.getArguments().size() > 127) {
-      //        throw new SemanticException(String.format("Too many arguments 
for function call
-      // %s()",
-      //            function.getSignature().getName().getFunctionName()));
-      //      }
-      //
-      //      BoundSignature signature = function.getSignature();
-      //      for (int i = 0; i < argumentTypes.size(); i++) {
-      //        Expression expression = node.getArguments().get(i);
-      //        Type expectedType = signature.getArgumentTypes().get(i);
-      //        if (expectedType == null) {
-      //          throw new NullPointerException(format("Type '%s' not found",
-      // signature.getArgumentTypes().get(i)));
-      //        }
-      //        if (node.isDistinct() && !expectedType.isComparable()) {
-      //          throw new SemanticException(String.format("DISTINCT can only 
be applied to
-      // comparable types (actual: %s)",
-      //              expectedType));
-      //        }
-      //        Type actualType =
-      // 
plannerContext.getTypeManager().getType(argumentTypes.get(i).getTypeSignature());
-      //
-      //        coerceType(expression, actualType, expectedType, 
String.format("Function %s argument
-      // %d", function, i));
-      //      }
-      //      resolvedFunctions.put(NodeRef.of(node), function);
-      //
-      //      Type type = signature.getReturnType();
-      //      return setExpressionType(node, type);
+      String functionName = node.getName().getSuffix();
+      boolean isAggregation = metadata.isAggregationFunction(session, 
functionName, accessControl);
+      // argument of the form `label.*` is only allowed for row pattern count 
function
+      node.getArguments().stream()
+          .filter(DereferenceExpression::isQualifiedAllFieldsReference)
+          .findAny()
+          .ifPresent(
+              allRowsReference -> {
+                if (node.getArguments().size() > 1) {
+                  throw new SemanticException(
+                      "label.* syntax is only supported as the only argument 
of row pattern count function");
+                }
+              });
+
+      if (node.isDistinct() && !isAggregation) {
+        throw new SemanticException("DISTINCT is not supported for 
non-aggregation functions");
+      }
+
+      List<Type> argumentTypes = getCallArgumentTypes(node.getArguments(), 
context);
+
+      if (node.getArguments().size() > 127) {
+        throw new SemanticException(
+            String.format("Too many arguments for function call %s()", 
functionName));
+      }
+
+      for (Type argumentType : argumentTypes) {
+        if (node.isDistinct() && !argumentType.isComparable()) {
+          throw new SemanticException(
+              String.format(
+                  "DISTINCT can only be applied to comparable types (actual: 
%s)", argumentType));
+        }
+      }
+
+      Type type = metadata.getFunctionReturnType(functionName, argumentTypes);
+      return setExpressionType(node, type);
     }
 
-    //    public List<TypeSignatureProvider> 
getCallArgumentTypes(List<Expression> arguments,
-    //
-    // StackableAstVisitorContext<Context> context) {
-    //      ImmutableList.Builder<TypeSignatureProvider> argumentTypesBuilder =
-    // ImmutableList.builder();
-    //      for (Expression argument : arguments) {
-    //        if (isQualifiedAllFieldsReference(argument)) {
-    //          // to resolve `count(label.*)` correctly, we should skip the 
argument, like for
-    // `count(*)`
-    //          // process the argument but do not include it in the list
-    //          DereferenceExpression allRowsDereference = 
(DereferenceExpression) argument;
-    //          String label = label((Identifier) 
allRowsDereference.getBase());
-    //          if (!context.getContext().getLabels().contains(label)) {
-    //            throw semanticException(INVALID_FUNCTION_ARGUMENT, 
allRowsDereference.getBase(),
-    //                "%s is not a primary pattern variable or subset name", 
label);
-    //          }
-    //          labelDereferences.put(NodeRef.of(allRowsDereference), new
-    // LabelPrefixedReference(label));
-    //        } else {
-    //          argumentTypesBuilder.add(new 
TypeSignatureProvider(process(argument,
-    // context).getTypeSignature()));
-    //        }
-    //      }
-    //
-    //      return argumentTypesBuilder.build();
-    //    }
+    public List<Type> getCallArgumentTypes(
+        List<Expression> arguments, StackableAstVisitorContext<Context> 
context) {
+      ImmutableList.Builder<Type> argumentTypesBuilder = 
ImmutableList.builder();
+      for (Expression argument : arguments) {
+        if (isQualifiedAllFieldsReference(argument)) {
+          // to resolve `count(label.*)` correctly, we should skip the 
argument, like for `count(*)`
+          // process the argument but do not include it in the list
+          DereferenceExpression allRowsDereference = (DereferenceExpression) 
argument;
+          String label = label((Identifier) allRowsDereference.getBase());
+          if (!context.getContext().getLabels().contains(label)) {
+            throw new SemanticException(
+                String.format("%s is not a primary pattern variable or subset 
name", label));
+          }
+          labelDereferences.put(NodeRef.of(allRowsDereference), new 
LabelPrefixedReference(label));
+        } else {
+          argumentTypesBuilder.add(process(argument, context));
+        }
+      }
+
+      return argumentTypesBuilder.build();
+    }
 
     private String label(Identifier identifier) {
       return identifier.getCanonicalValue();
@@ -849,38 +809,17 @@ public class ExpressionAnalyzer {
 
     @Override
     protected Type visitTrim(Trim node, StackableAstVisitorContext<Context> 
context) {
-      // TODO implement TRIM
-      throw new SemanticException("Trim is not implemented yet");
-      //      ImmutableList.Builder<Type> argumentTypes = 
ImmutableList.builder();
-      //
-      //      argumentTypes.add(process(node.getTrimSource(), context));
-      //      node.getTrimCharacter().ifPresent(trimChar -> 
argumentTypes.add(process(trimChar,
-      // context)));
-      //      List<Type> actualTypes = argumentTypes.build();
-      //
-      //      String functionName = node.getSpecification().getFunctionName();
-      //      ResolvedFunction function =
-      //          
plannerContext.getMetadata().resolveBuiltinFunction(functionName,
-      // fromTypes(actualTypes));
-      //
-      //      List<Type> expectedTypes = 
function.getSignature().getArgumentTypes();
-      //      checkState(expectedTypes.size() == actualTypes.size(), "wrong 
argument number in the
-      // resolved signature");
-      //
-      //      Type actualTrimSourceType = actualTypes.get(0);
-      //      Type expectedTrimSourceType = expectedTypes.get(0);
-      //      coerceType(node.getTrimSource(), actualTrimSourceType, 
expectedTrimSourceType,
-      //          "source argument of trim function");
-      //
-      //      if (node.getTrimCharacter().isPresent()) {
-      //        Type actualTrimCharType = actualTypes.get(1);
-      //        Type expectedTrimCharType = expectedTypes.get(1);
-      //        coerceType(node.getTrimCharacter().get(), actualTrimCharType, 
expectedTrimCharType,
-      //            "trim character argument of trim function");
-      //      }
-      //      resolvedFunctions.put(NodeRef.of(node), function);
-      //
-      //      return setExpressionType(node, 
function.getSignature().getReturnType());
+      ImmutableList.Builder<Type> argumentTypes = ImmutableList.builder();
+
+      argumentTypes.add(process(node.getTrimSource(), context));
+      node.getTrimCharacter().ifPresent(trimChar -> 
argumentTypes.add(process(trimChar, context)));
+      List<Type> actualTypes = argumentTypes.build();
+
+      String functionName = node.getSpecification().getFunctionName();
+
+      Type returnType = metadata.getFunctionReturnType(functionName, 
actualTypes);
+
+      return setExpressionType(node, returnType);
     }
 
     @Override
@@ -926,31 +865,26 @@ public class ExpressionAnalyzer {
 
     @Override
     public Type visitCast(Cast node, StackableAstVisitorContext<Context> 
context) {
-      // TODO implement cast
-      throw new SemanticException("Cast is not implemented yet");
-      //
-      //      Type type;
-      //      try {
-      //        type = 
plannerContext.getTypeManager().getType(toTypeSignature(node.getType()));
-      //      } catch (TypeNotFoundException e) {
-      //        throw semanticException(TYPE_MISMATCH, node, "Unknown type: 
%s", node.getType());
-      //      }
-      //
-      //      if (type.equals(UnknownType.UNKNOWN)) {
-      //        throw new SemanticException("UNKNOWN is not a valid type");
-      //      }
-      //
-      //      Type value = process(node.getExpression(), context);
-      //      if (!value.equals(UnknownType.UNKNOWN) && !node.isTypeOnly()) {
-      //        // TODO implement cast
-      //        try {
-      //          plannerContext.getMetadata().getCoercion(value, type);
-      //        } catch (OperatorNotFoundException e) {
-      //          throw semanticException(TYPE_MISMATCH, node, "Cannot cast %s 
to %s", value, type);
-      //        }
-      //      }
-      //
-      //      return setExpressionType(node, type);
+
+      Type type;
+      try {
+        type = metadata.getType(toTypeSignature(node.getType()));
+      } catch (TypeNotFoundException e) {
+        throw new SemanticException(String.format("Unknown type: %s", 
node.getType()));
+      }
+
+      if (type.equals(UnknownType.UNKNOWN)) {
+        throw new SemanticException("UNKNOWN is not a valid type");
+      }
+
+      Type value = process(node.getExpression(), context);
+      if (!value.equals(UnknownType.UNKNOWN)
+          && !node.isTypeOnly()
+          && (!metadata.canCoerce(value, type))) {
+        throw new SemanticException(String.format("Cannot cast %s to %s", 
value, type));
+      }
+
+      return setExpressionType(node, type);
     }
 
     @Override
@@ -1158,25 +1092,13 @@ public class ExpressionAnalyzer {
         argumentTypes.add(process(expression, context));
       }
 
-      BoundSignature operatorSignature;
+      Type type;
       try {
-        operatorSignature =
-            metadata.resolveOperator(operatorType, 
argumentTypes.build()).getSignature();
+        type = metadata.getOperatorReturnType(operatorType, 
argumentTypes.build());
       } catch (OperatorNotFoundException e) {
         throw new SemanticException(e.getMessage());
       }
 
-      for (int i = 0; i < arguments.length; i++) {
-        Expression expression = arguments[i];
-        Type type = operatorSignature.getArgumentTypes().get(i);
-        coerceType(
-            context,
-            expression,
-            type,
-            String.format("Operator %s argument %d", operatorSignature, i));
-      }
-
-      Type type = operatorSignature.getReturnType();
       return setExpressionType(node, type);
     }
 
@@ -1382,10 +1304,9 @@ public class ExpressionAnalyzer {
       return functionInputTypes;
     }
 
-    //    public Set<String> getLabels() {
-    //      checkState(isPatternRecognition());
-    //      return labels;
-    //    }
+    public Set<String> getLabels() {
+      return labels;
+    }
 
     public CorrelationSupport getCorrelationSupport() {
       return correlationSupport;
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/BuiltinFunctionResolver.java
similarity index 83%
copy from 
iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/BuiltinFunctionResolver.java
index ed3e7b99fe5..991b38d18b3 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/BuiltinFunctionResolver.java
@@ -17,22 +17,6 @@
  * under the License.
  */
 
-package org.apache.iotdb.tsfile.read.common.type;
+package org.apache.iotdb.db.queryengine.plan.relational.metadata;
 
-public enum TypeEnum {
-  INT32,
-
-  INT64,
-
-  FLOAT,
-
-  DOUBLE,
-
-  BOOLEAN,
-
-  BINARY,
-
-  ROW,
-
-  UNKNOWN
-}
+public class BuiltinFunctionResolver {}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java
index 5e708b9c9f0..00843f38201 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java
@@ -21,6 +21,9 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.metadata;
 
 import org.apache.iotdb.db.queryengine.common.SessionInfo;
 import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType;
+import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
+import 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundException;
+import org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignature;
 import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.util.List;
@@ -61,4 +64,16 @@ public interface Metadata {
 
   ResolvedFunction resolveOperator(OperatorType operatorType, List<? extends 
Type> argumentTypes)
       throws OperatorNotFoundException;
+
+  Type getOperatorReturnType(OperatorType operatorType, List<? extends Type> 
argumentTypes)
+      throws OperatorNotFoundException;
+
+  Type getFunctionReturnType(String functionName, List<? extends Type> 
argumentTypes);
+
+  boolean isAggregationFunction(
+      SessionInfo session, String functionName, AccessControl accessControl);
+
+  Type getType(TypeSignature signature) throws TypeNotFoundException;
+
+  boolean canCoerce(Type from, Type to);
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
index 95fcfcaacbe..f040a086142 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
@@ -19,15 +19,35 @@
 
 package org.apache.iotdb.db.queryengine.plan.relational.metadata;
 
+import org.apache.iotdb.commons.udf.builtin.BuiltinAggregationFunction;
+import org.apache.iotdb.commons.udf.builtin.BuiltinScalarFunction;
+import org.apache.iotdb.db.exception.sql.SemanticException;
 import org.apache.iotdb.db.queryengine.common.SessionInfo;
 import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType;
+import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
+import 
org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager;
+import org.apache.iotdb.db.queryengine.plan.relational.type.TypeManager;
+import 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundException;
+import org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignature;
+import org.apache.iotdb.db.utils.constant.SqlConstant;
 import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 
+import static org.apache.iotdb.tsfile.read.common.type.BinaryType.TEXT;
+import static org.apache.iotdb.tsfile.read.common.type.BooleanType.BOOLEAN;
+import static org.apache.iotdb.tsfile.read.common.type.DoubleType.DOUBLE;
+import static org.apache.iotdb.tsfile.read.common.type.FloatType.FLOAT;
+import static org.apache.iotdb.tsfile.read.common.type.IntType.INT32;
+import static org.apache.iotdb.tsfile.read.common.type.LongType.INT64;
+
 public class TableMetadataImpl implements Metadata {
+
+  private final TypeManager typeManager = new InternalTypeManager();
+
   @Override
   public boolean tableExists(QualifiedObjectName name) {
     return false;
@@ -59,4 +79,210 @@ public class TableMetadataImpl implements Metadata {
       throws OperatorNotFoundException {
     return null;
   }
+
+  @Override
+  public Type getOperatorReturnType(OperatorType operatorType, List<? extends 
Type> argumentTypes)
+      throws OperatorNotFoundException {
+
+    switch (operatorType) {
+      case ADD:
+      case SUBTRACT:
+      case MULTIPLY:
+      case DIVIDE:
+      case MODULUS:
+        if (!isTwoNumericType(argumentTypes)) {
+          throw new OperatorNotFoundException(
+              operatorType,
+              argumentTypes,
+              new IllegalArgumentException("Should have two numeric 
operands."));
+        }
+        return DOUBLE;
+      case NEGATION:
+        if (!isOneNumericType(argumentTypes)) {
+          throw new OperatorNotFoundException(
+              operatorType,
+              argumentTypes,
+              new IllegalArgumentException("Should have one numeric 
operands."));
+        }
+        return DOUBLE;
+      case EQUAL:
+      case LESS_THAN:
+      case LESS_THAN_OR_EQUAL:
+        if (!isTwoTypeComparable(argumentTypes)) {
+          throw new OperatorNotFoundException(
+              operatorType,
+              argumentTypes,
+              new IllegalArgumentException("Should have two comparable 
operands."));
+        }
+        return BOOLEAN;
+      default:
+        throw new OperatorNotFoundException(
+            operatorType, argumentTypes, new UnsupportedOperationException());
+    }
+  }
+
+  @Override
+  public Type getFunctionReturnType(String functionName, List<? extends Type> 
argumentTypes) {
+
+    // builtin scalar function
+    if 
(BuiltinScalarFunction.DIFF.getFunctionName().equalsIgnoreCase(functionName)
+        || 
BuiltinScalarFunction.ROUND.getFunctionName().equalsIgnoreCase(functionName)) {
+      if (!isOneNumericType(argumentTypes)) {
+        throw new SemanticException(
+            "Scalar function"
+                + functionName.toLowerCase(Locale.ENGLISH)
+                + " only supports numeric data types [INT32, INT64, FLOAT, 
DOUBLE]");
+      }
+      return DOUBLE;
+    } else if 
(BuiltinScalarFunction.REPLACE.getFunctionName().equalsIgnoreCase(functionName)
+        || 
BuiltinScalarFunction.SUBSTRING.getFunctionName().equalsIgnoreCase(functionName))
 {
+      if (!isOneTextType(argumentTypes)) {
+        throw new SemanticException(
+            "Scalar function"
+                + functionName.toLowerCase(Locale.ENGLISH)
+                + " only supports text data type.");
+      }
+      return TEXT;
+    }
+
+    // builtin aggregation function
+    // check argument type
+    switch (functionName.toLowerCase()) {
+      case SqlConstant.AVG:
+      case SqlConstant.SUM:
+      case SqlConstant.EXTREME:
+      case SqlConstant.MIN_VALUE:
+      case SqlConstant.MAX_VALUE:
+      case SqlConstant.STDDEV:
+      case SqlConstant.STDDEV_POP:
+      case SqlConstant.STDDEV_SAMP:
+      case SqlConstant.VARIANCE:
+      case SqlConstant.VAR_POP:
+      case SqlConstant.VAR_SAMP:
+        if (!isOneNumericType(argumentTypes)) {
+          throw new SemanticException(
+              String.format(
+                  "Aggregate functions [%s] only support numeric data types 
[INT32, INT64, FLOAT, DOUBLE]",
+                  functionName));
+        }
+        break;
+      case SqlConstant.MIN_TIME:
+      case SqlConstant.MAX_TIME:
+      case SqlConstant.FIRST_VALUE:
+      case SqlConstant.LAST_VALUE:
+      case SqlConstant.TIME_DURATION:
+      case SqlConstant.MODE:
+        if (argumentTypes.size() != 1) {
+          throw new SemanticException(
+              String.format(
+                  "Aggregate functions [%s] should only have one argument", 
functionName));
+        }
+        break;
+      case SqlConstant.MAX_BY:
+      case SqlConstant.MIN_BY:
+        if (argumentTypes.size() != 2) {
+          throw new SemanticException(
+              String.format(
+                  "Aggregate functions [%s] should only have two arguments", 
functionName));
+        } else if (!argumentTypes.get(1).isOrderable()) {
+          throw new SemanticException(
+              String.format(
+                  "Second argument of Aggregate functions [%s] should be 
orderable", functionName));
+        }
+
+        break;
+      case SqlConstant.COUNT:
+        break;
+      default:
+        // ignore
+    }
+
+    // get return type
+    switch (functionName.toLowerCase()) {
+      case SqlConstant.MIN_TIME:
+      case SqlConstant.MAX_TIME:
+      case SqlConstant.COUNT:
+      case SqlConstant.TIME_DURATION:
+        return INT64;
+      case SqlConstant.MIN_VALUE:
+      case SqlConstant.LAST_VALUE:
+      case SqlConstant.FIRST_VALUE:
+      case SqlConstant.MAX_VALUE:
+      case SqlConstant.EXTREME:
+      case SqlConstant.MODE:
+      case SqlConstant.MAX_BY:
+      case SqlConstant.MIN_BY:
+        return argumentTypes.get(0);
+      case SqlConstant.AVG:
+      case SqlConstant.SUM:
+      case SqlConstant.STDDEV:
+      case SqlConstant.STDDEV_POP:
+      case SqlConstant.STDDEV_SAMP:
+      case SqlConstant.VARIANCE:
+      case SqlConstant.VAR_POP:
+      case SqlConstant.VAR_SAMP:
+        return DOUBLE;
+      default:
+        // ignore
+    }
+
+    // TODO scalar UDF function
+
+    // TODO UDAF
+
+    throw new SemanticException("Unknown function: " + functionName);
+  }
+
+  @Override
+  public boolean isAggregationFunction(
+      SessionInfo session, String functionName, AccessControl accessControl) {
+    return BuiltinAggregationFunction.getNativeFunctionNames()
+        .contains(functionName.toLowerCase(Locale.ENGLISH));
+  }
+
+  @Override
+  public Type getType(TypeSignature signature) throws TypeNotFoundException {
+    return typeManager.getType(signature);
+  }
+
+  @Override
+  public boolean canCoerce(Type from, Type to) {
+    return true;
+  }
+
+  public static boolean isTwoNumericType(List<? extends Type> argumentTypes) {
+    return argumentTypes.size() == 2
+        && isNumericType(argumentTypes.get(0))
+        && isNumericType(argumentTypes.get(1));
+  }
+
+  public static boolean isOneNumericType(List<? extends Type> argumentTypes) {
+    return argumentTypes.size() == 1 && isNumericType(argumentTypes.get(0));
+  }
+
+  public static boolean isOneBooleanType(List<? extends Type> argumentTypes) {
+    return argumentTypes.size() == 1 && BOOLEAN.equals(argumentTypes.get(0));
+  }
+
+  public static boolean isOneTextType(List<? extends Type> argumentTypes) {
+    return argumentTypes.size() == 1 && TEXT.equals(argumentTypes.get(0));
+  }
+
+  public static boolean isNumericType(Type type) {
+    return DOUBLE.equals(type) || FLOAT.equals(type) || INT32.equals(type) || 
INT64.equals(type);
+  }
+
+  public static boolean isTwoTypeComparable(List<? extends Type> 
argumentTypes) {
+    if (argumentTypes.size() != 2) {
+      return false;
+    }
+    Type left = argumentTypes.get(0);
+    Type right = argumentTypes.get(1);
+    if (left.equals(right)) {
+      return true;
+    }
+
+    // Boolean type and Binary Type can not be compared with other types
+    return isNumericType(left) && isNumericType(right);
+  }
 }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java
similarity index 53%
copy from 
iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java
index ed3e7b99fe5..b8090df85d4 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java
@@ -17,22 +17,24 @@
  * under the License.
  */
 
-package org.apache.iotdb.tsfile.read.common.type;
+package org.apache.iotdb.db.queryengine.plan.relational.planner;
 
-public enum TypeEnum {
-  INT32,
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
+import org.apache.iotdb.db.queryengine.plan.relational.type.TypeManager;
 
-  INT64,
-
-  FLOAT,
-
-  DOUBLE,
-
-  BOOLEAN,
+/**
+ * A carrier of core, global, non-derived services for planner and analyzer. 
This is used to ease
+ * the addition of new services in the future without having to modify large 
portions the planner
+ * and analyzer just to pass around the service.
+ */
+public class PlannerContext {
 
-  BINARY,
+  private final Metadata metadata;
 
-  ROW,
+  private final TypeManager typeManager;
 
-  UNKNOWN
+  public PlannerContext(Metadata metadata, TypeManager typeManager) {
+    this.metadata = metadata;
+    this.typeManager = typeManager;
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/InternalTypeManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/InternalTypeManager.java
new file mode 100644
index 00000000000..3b3cdf32bc3
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/InternalTypeManager.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.queryengine.plan.relational.type;
+
+import org.apache.iotdb.tsfile.read.common.type.Type;
+import org.apache.iotdb.tsfile.read.common.type.TypeEnum;
+
+import java.util.Locale;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.apache.iotdb.tsfile.read.common.type.BinaryType.TEXT;
+import static org.apache.iotdb.tsfile.read.common.type.BooleanType.BOOLEAN;
+import static org.apache.iotdb.tsfile.read.common.type.DoubleType.DOUBLE;
+import static org.apache.iotdb.tsfile.read.common.type.FloatType.FLOAT;
+import static org.apache.iotdb.tsfile.read.common.type.IntType.INT32;
+import static org.apache.iotdb.tsfile.read.common.type.LongType.INT64;
+
+public class InternalTypeManager implements TypeManager {
+
+  private final ConcurrentMap<TypeSignature, Type> types = new 
ConcurrentHashMap<>();
+
+  public InternalTypeManager() {
+    types.put(new 
TypeSignature(TypeEnum.DOUBLE.name().toLowerCase(Locale.ENGLISH)), DOUBLE);
+    types.put(new 
TypeSignature(TypeEnum.FLOAT.name().toLowerCase(Locale.ENGLISH)), FLOAT);
+    types.put(new 
TypeSignature(TypeEnum.INT64.name().toLowerCase(Locale.ENGLISH)), INT64);
+    types.put(new 
TypeSignature(TypeEnum.INT32.name().toLowerCase(Locale.ENGLISH)), INT32);
+    types.put(new 
TypeSignature(TypeEnum.BOOLEAN.name().toLowerCase(Locale.ENGLISH)), BOOLEAN);
+    types.put(new 
TypeSignature(TypeEnum.TEXT.name().toLowerCase(Locale.ENGLISH)), TEXT);
+  }
+
+  @Override
+  public Type getType(TypeSignature signature) throws TypeNotFoundException {
+    Type type = types.get(signature);
+    if (type == null) {
+      throw new TypeNotFoundException(signature);
+    }
+    return type;
+  }
+
+  @Override
+  public Type fromSqlType(String type) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public Type getType(TypeId id) {
+    throw new UnsupportedOperationException();
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeId.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeId.java
new file mode 100644
index 00000000000..9f445377fbb
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeId.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.queryengine.plan.relational.type;
+
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Represents an opaque identifier for a Type than can be used for 
serialization or storage in
+ * external systems.
+ */
+public class TypeId {
+  private final String id;
+
+  private TypeId(String id) {
+    this.id = requireNonNull(id, "id is null");
+  }
+
+  public static TypeId of(String id) {
+    return new TypeId(id);
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    TypeId typeId = (TypeId) o;
+    return id.equals(typeId.id);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id);
+  }
+
+  @Override
+  public String toString() {
+    return "type:[" + getId() + "]";
+  }
+}
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
similarity index 62%
copy from 
iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
index ed3e7b99fe5..ed6dd267e0b 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
@@ -17,22 +17,21 @@
  * under the License.
  */
 
-package org.apache.iotdb.tsfile.read.common.type;
+package org.apache.iotdb.db.queryengine.plan.relational.type;
 
-public enum TypeEnum {
-  INT32,
+import org.apache.iotdb.tsfile.read.common.type.Type;
 
-  INT64,
+public interface TypeManager {
+  /**
+   * Gets the type with the specified signature.
+   *
+   * @throws TypeNotFoundException if not found
+   */
+  Type getType(TypeSignature signature) throws TypeNotFoundException;
 
-  FLOAT,
+  /** Gets a type given it's SQL representation */
+  Type fromSqlType(String type);
 
-  DOUBLE,
-
-  BOOLEAN,
-
-  BINARY,
-
-  ROW,
-
-  UNKNOWN
+  /** Gets the type with the give (opaque) id */
+  Type getType(TypeId id);
 }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java
similarity index 55%
copy from 
iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java
index ed3e7b99fe5..20d7281abf8 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java
@@ -17,22 +17,27 @@
  * under the License.
  */
 
-package org.apache.iotdb.tsfile.read.common.type;
+package org.apache.iotdb.db.queryengine.plan.relational.type;
 
-public enum TypeEnum {
-  INT32,
+import org.apache.iotdb.commons.exception.IoTDBException;
 
-  INT64,
+import static java.util.Objects.requireNonNull;
+import static org.apache.iotdb.rpc.TSStatusCode.TYPE_NOT_FOUND;
 
-  FLOAT,
+public class TypeNotFoundException extends IoTDBException {
 
-  DOUBLE,
+  private final TypeSignature type;
 
-  BOOLEAN,
+  public TypeNotFoundException(TypeSignature type) {
+    this(type, null);
+  }
 
-  BINARY,
+  public TypeNotFoundException(TypeSignature type, Throwable cause) {
+    super("Unknown type: " + type, cause, TYPE_NOT_FOUND.getStatusCode());
+    this.type = requireNonNull(type, "type is null");
+  }
 
-  ROW,
-
-  UNKNOWN
+  public TypeSignature getType() {
+    return type;
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeSignatureTranslator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeSignatureTranslator.java
new file mode 100644
index 00000000000..5a65111666e
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeSignatureTranslator.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.queryengine.plan.relational.type;
+
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.relational.sql.tree.DataType;
+import org.apache.iotdb.db.relational.sql.tree.DataTypeParameter;
+import org.apache.iotdb.db.relational.sql.tree.GenericDataType;
+import org.apache.iotdb.db.relational.sql.tree.Identifier;
+import org.apache.iotdb.db.relational.sql.tree.NumericParameter;
+import org.apache.iotdb.db.relational.sql.tree.TypeParameter;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.Collections;
+import java.util.Locale;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureParameter.numericParameter;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureParameter.typeParameter;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureParameter.typeVariable;
+
+public class TypeSignatureTranslator {
+
+  private TypeSignatureTranslator() {}
+
+  public static TypeSignature toTypeSignature(DataType type) {
+    return toTypeSignature(type, Collections.emptySet());
+  }
+
+  private static TypeSignature toTypeSignature(DataType type, Set<String> 
typeVariables) {
+    if (type instanceof GenericDataType) {
+      return toTypeSignature((GenericDataType) type, typeVariables);
+    }
+
+    throw new UnsupportedOperationException("Unsupported DataType: " + 
type.getClass().getName());
+  }
+
+  private static TypeSignature toTypeSignature(GenericDataType type, 
Set<String> typeVariables) {
+    ImmutableList.Builder<TypeSignatureParameter> parameters = 
ImmutableList.builder();
+
+    //    if (type.getName().getValue().equalsIgnoreCase(VARCHAR) && 
type.getArguments().isEmpty())
+    // {
+    //      // We treat VARCHAR specially because currently, the unbounded 
VARCHAR type is modeled
+    // in the system as a VARCHAR(n) with a "magic" length
+    //      // TODO: Eventually, we should split the types into VARCHAR and 
VARCHAR(n)
+    //      return VarcharType.VARCHAR.getTypeSignature();
+    //    }
+
+    checkArgument(
+        !typeVariables.contains(type.getName().getValue()),
+        "Base type name cannot be a type variable");
+
+    for (DataTypeParameter parameter : type.getArguments()) {
+      if (parameter instanceof NumericParameter) {
+        String value = ((NumericParameter) parameter).getValue();
+        try {
+          parameters.add(numericParameter(Long.parseLong(value)));
+        } catch (NumberFormatException e) {
+          throw new SemanticException(String.format("Invalid type parameter: 
%s", value));
+        }
+      } else if (parameter instanceof TypeParameter) {
+        DataType value = ((TypeParameter) parameter).getValue();
+        if (value instanceof GenericDataType
+            && ((GenericDataType) value).getArguments().isEmpty()
+            && typeVariables.contains(((GenericDataType) 
value).getName().getValue())) {
+          parameters.add(typeVariable(((GenericDataType) 
value).getName().getValue()));
+        } else {
+          parameters.add(typeParameter(toTypeSignature(value, typeVariables)));
+        }
+      } else {
+        throw new UnsupportedOperationException(
+            "Unsupported type parameter kind: " + 
parameter.getClass().getName());
+      }
+    }
+
+    return new TypeSignature(canonicalize(type.getName()), parameters.build());
+  }
+
+  private static String canonicalize(Identifier identifier) {
+    if (identifier.isDelimited()) {
+      return identifier.getValue();
+    }
+
+    return identifier
+        .getValue()
+        .toLowerCase(Locale.ENGLISH); // TODO: make this toUpperCase to match 
standard SQL semantics
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/CompareBinaryColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/CompareBinaryColumnTransformer.java
index 15c481c5cea..a352ac017be 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/CompareBinaryColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/CompareBinaryColumnTransformer.java
@@ -48,7 +48,7 @@ public abstract class CompareBinaryColumnTransformer extends 
BinaryColumnTransfo
       if (!leftColumn.isNull(i) && !rightColumn.isNull(i)) {
         boolean flag = false;
         // compare binary type
-        if (TypeEnum.BINARY.equals(leftTransformer.getType().getTypeEnum())) {
+        if (TypeEnum.TEXT.equals(leftTransformer.getType().getTypeEnum())) {
           flag =
               transform(
                   TransformUtils.compare(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
index 6379ae04e9f..e7b31815f62 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
@@ -54,9 +54,9 @@ public abstract class CompareTernaryColumnTransformer extends 
TernaryColumnTrans
     if (firstColumnTransformer.isReturnTypeNumeric()
             && secondColumnTransformer.isReturnTypeNumeric()
             && thirdColumnTransformer.isReturnTypeNumeric()
-        || firstColumnTransformer.typeEquals(TypeEnum.BINARY)
-            && secondColumnTransformer.typeEquals(TypeEnum.BINARY)
-            && thirdColumnTransformer.typeEquals(TypeEnum.BINARY)) {
+        || firstColumnTransformer.typeEquals(TypeEnum.TEXT)
+            && secondColumnTransformer.typeEquals(TypeEnum.TEXT)
+            && thirdColumnTransformer.typeEquals(TypeEnum.TEXT)) {
       return;
     }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java
index 23c7e6a5298..6aa7e0797c8 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java
@@ -76,7 +76,7 @@ public class InColumnTransformer extends 
UnaryColumnTransformer {
           case BOOLEAN:
             returnType.writeBoolean(columnBuilder, 
satisfy.of(column.getBoolean(i)));
             break;
-          case BINARY:
+          case TEXT:
             returnType.writeBoolean(
                 columnBuilder,
                 
satisfy.of(column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET)));
@@ -142,7 +142,7 @@ public class InColumnTransformer extends 
UnaryColumnTransformer {
           booleanSet.add(strictCastToBool(value));
         }
         break;
-      case BINARY:
+      case TEXT:
         stringSet = values;
         break;
       default:
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/RegularColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/RegularColumnTransformer.java
index eb48fa3ef79..f010008b695 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/RegularColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/RegularColumnTransformer.java
@@ -58,7 +58,7 @@ public class RegularColumnTransformer extends 
UnaryColumnTransformer {
 
   @Override
   protected void checkType() {
-    if (!childColumnTransformer.typeEquals(TypeEnum.BINARY)) {
+    if (!childColumnTransformer.typeEquals(TypeEnum.TEXT)) {
       throw new UnsupportedOperationException(
           "Unsupported Type: " + 
childColumnTransformer.getType().getTypeEnum());
     }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/CastFunctionColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/CastFunctionColumnTransformer.java
index b1b9dac06fc..2d76882f42f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/CastFunctionColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/CastFunctionColumnTransformer.java
@@ -60,7 +60,7 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
           case BOOLEAN:
             cast(columnBuilder, childType.getBoolean(column, i));
             break;
-          case BINARY:
+          case TEXT:
             cast(columnBuilder, childType.getBinary(column, i));
             break;
           default:
@@ -92,7 +92,7 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
       case BOOLEAN:
         returnType.writeBoolean(columnBuilder, value != 0);
         break;
-      case BINARY:
+      case TEXT:
         returnType.writeBinary(columnBuilder, 
BytesUtils.valueOf(String.valueOf(value)));
         break;
       default:
@@ -117,7 +117,7 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
       case BOOLEAN:
         returnType.writeBoolean(columnBuilder, value != 0L);
         break;
-      case BINARY:
+      case TEXT:
         returnType.writeBinary(columnBuilder, 
BytesUtils.valueOf(String.valueOf(value)));
         break;
       default:
@@ -142,7 +142,7 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
       case BOOLEAN:
         returnType.writeBoolean(columnBuilder, value != 0.0f);
         break;
-      case BINARY:
+      case TEXT:
         returnType.writeBinary(columnBuilder, 
BytesUtils.valueOf(String.valueOf(value)));
         break;
       default:
@@ -167,7 +167,7 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
       case BOOLEAN:
         returnType.writeBoolean(columnBuilder, value != 0.0);
         break;
-      case BINARY:
+      case TEXT:
         returnType.writeBinary(columnBuilder, 
BytesUtils.valueOf(String.valueOf(value)));
         break;
       default:
@@ -192,7 +192,7 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
       case BOOLEAN:
         returnType.writeBoolean(columnBuilder, value);
         break;
-      case BINARY:
+      case TEXT:
         returnType.writeBinary(columnBuilder, 
BytesUtils.valueOf(String.valueOf(value)));
         break;
       default:
@@ -218,7 +218,7 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
       case BOOLEAN:
         returnType.writeBoolean(columnBuilder, 
CastFunctionHelper.castTextToBoolean(stringValue));
         break;
-      case BINARY:
+      case TEXT:
         returnType.writeBinary(columnBuilder, value);
         break;
       default:
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java
index 62ac6cae73c..486f18c761b 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java
@@ -12,6 +12,9 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.ResolvedFunction
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableHandle;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadata;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableSchema;
+import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
+import 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundException;
+import org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignature;
 import org.apache.iotdb.tsfile.read.common.type.BinaryType;
 import org.apache.iotdb.tsfile.read.common.type.DoubleType;
 import org.apache.iotdb.tsfile.read.common.type.Type;
@@ -106,4 +109,31 @@ public class TestMatadata implements Metadata {
       throws OperatorNotFoundException {
     return null;
   }
+
+  @Override
+  public Type getOperatorReturnType(OperatorType operatorType, List<? extends 
Type> argumentTypes)
+      throws OperatorNotFoundException {
+    return null;
+  }
+
+  @Override
+  public Type getFunctionReturnType(String functionName, List<? extends Type> 
argumentTypes) {
+    return null;
+  }
+
+  @Override
+  public boolean isAggregationFunction(
+      SessionInfo session, String functionName, AccessControl accessControl) {
+    return false;
+  }
+
+  @Override
+  public Type getType(TypeSignature signature) throws TypeNotFoundException {
+    return null;
+  }
+
+  @Override
+  public boolean canCoerce(Type from, Type to) {
+    return false;
+  }
 }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java
index 19c9551942e..47febb3315e 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java
@@ -49,7 +49,7 @@ public class BinaryType implements Type {
 
   @Override
   public TypeEnum getTypeEnum() {
-    return TypeEnum.BINARY;
+    return TypeEnum.TEXT;
   }
 
   @Override
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
index ed3e7b99fe5..6d38bf6f1e8 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
@@ -30,7 +30,7 @@ public enum TypeEnum {
 
   BOOLEAN,
 
-  BINARY,
+  TEXT,
 
   ROW,
 
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeFactory.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeFactory.java
index 7a82fdb8ae2..751e25a2169 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeFactory.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeFactory.java
@@ -59,7 +59,7 @@ public class TypeFactory {
         return DoubleType.getInstance();
       case BOOLEAN:
         return BooleanType.getInstance();
-      case BINARY:
+      case TEXT:
         return BinaryType.getInstance();
       case UNKNOWN:
         return UnknownType.getInstance();

Reply via email to