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

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

commit fbea5bdbeb6114aa8724dbd53d5cd868da05941b
Author: JackieTien97 <[email protected]>
AuthorDate: Tue Aug 27 21:12:28 2024 +0800

    init
---
 .../relational/ColumnTransformerBuilder.java       |  38 +-
 .../InterpretedFunctionInvoker.java}               |  18 +-
 .../FunctionManager.java}                          |  21 +-
 .../planner/IrExpressionInterpreter.java           |  93 ++++
 .../plan/relational/planner/IrTypeAnalyzer.java    | 491 +++++++++++++++++++++
 .../plan/relational/planner/LiteralEncoder.java    | 126 ++++++
 .../relational/planner/LiteralInterpreter.java     | 112 +++++
 .../plan/relational/planner/PlannerContext.java    |   4 +
 .../AllowAllAccessControl.java}                    |  18 +-
 .../plan/relational/sql/ast/BinaryLiteral.java     |   9 +
 .../plan/relational/sql/ast/DoubleLiteral.java     |   5 +
 .../type/{TypeManager.java => TypeCoercion.java}   |  20 +-
 .../plan/relational/type/TypeManager.java          |   2 +-
 .../relational/type/TypeNotFoundException.java     |   4 +-
 .../relational/type/TypeSignatureTranslator.java   |   7 +
 15 files changed, 907 insertions(+), 61 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
index bdaa1f2ea1c..0a0bae7629a 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
@@ -41,6 +41,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DecimalLiteral;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FunctionCall;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.GenericLiteral;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IfExpression;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InListExpression;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InPredicate;
@@ -152,6 +153,8 @@ import 
org.apache.tsfile.read.common.block.column.BooleanColumn;
 import org.apache.tsfile.read.common.block.column.DoubleColumn;
 import org.apache.tsfile.read.common.block.column.IntColumn;
 import org.apache.tsfile.read.common.block.column.LongColumn;
+import org.apache.tsfile.read.common.type.DateType;
+import org.apache.tsfile.read.common.type.TimestampType;
 import org.apache.tsfile.read.common.type.Type;
 import org.apache.tsfile.read.common.type.TypeEnum;
 import org.apache.tsfile.utils.Binary;
@@ -427,6 +430,37 @@ public class ColumnTransformerBuilder
     throw new UnsupportedOperationException();
   }
 
+  @Override
+  protected ColumnTransformer visitGenericLiteral(GenericLiteral node, Context 
context) {
+    ColumnTransformer res =
+        context.cache.computeIfAbsent(
+            node,
+            e -> {
+              ConstantColumnTransformer columnTransformer = 
getColumnTransformerForGenericLiteral(node);
+              context.leafList.add(columnTransformer);
+              return columnTransformer;
+            });
+    res.addReferenceCount();
+    return res;
+  }
+
+  // currently, we only support Date and Timestamp
+  // for Date, GenericLiteral.value is an int value
+  // for Timestamp, GenericLiteral.value is a long value
+  private static ConstantColumnTransformer 
getColumnTransformerForGenericLiteral(GenericLiteral literal) {
+    if (DateType.DATE.getTypeEnum().name().equals(literal.getType())) {
+      return new ConstantColumnTransformer(
+          DateType.DATE,
+          new IntColumn(1, Optional.empty(), new int[] 
{Integer.parseInt(literal.getValue())}));
+    } else if 
(TimestampType.TIMESTAMP.getTypeEnum().name().equals(literal.getType())) {
+      return new ConstantColumnTransformer(
+          TimestampType.TIMESTAMP,
+          new LongColumn(1, Optional.empty(), new long[] 
{Long.parseLong(literal.getValue())}));
+    } else {
+      throw new IllegalArgumentException("Unsupported type in GenericLiteral: 
" + literal.getType());
+    }
+  }
+
   @Override
   protected ColumnTransformer visitNullLiteral(NullLiteral node, Context 
context) {
     ColumnTransformer res =
@@ -982,7 +1016,7 @@ public class ColumnTransformerBuilder
       case DATE:
         Set<Integer> dateSet = new HashSet<>();
         for (Literal value : values) {
-          dateSet.add(DateUtils.parseDateExpressionToInt(((StringLiteral) 
value).getValue()));
+          dateSet.add(Integer.parseInt(((GenericLiteral) value).getValue()));
         }
         return new InInt32MultiColumnTransformer(dateSet, 
valueColumnTransformerList);
       case INT64:
@@ -990,7 +1024,7 @@ public class ColumnTransformerBuilder
         Set<Long> longSet = new HashSet<>();
         for (Literal value : values) {
           try {
-            longSet.add((((LongLiteral) value).getParsedValue()));
+            longSet.add(Long.parseLong(((GenericLiteral) value).getValue()));
           } catch (IllegalArgumentException e) {
             throw new SemanticException(String.format(errorMsg, value, 
childType));
           }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/InterpretedFunctionInvoker.java
similarity index 62%
copy from 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/InterpretedFunctionInvoker.java
index 1830db19e19..6f370c35e46 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/InterpretedFunctionInvoker.java
@@ -17,21 +17,7 @@
  * under the License.
  */
 
-package org.apache.iotdb.db.queryengine.plan.relational.type;
+package org.apache.iotdb.db.queryengine.plan.relational.function;
 
-import org.apache.tsfile.read.common.type.Type;
-
-public interface TypeManager {
-  /**
-   * Gets the type with the specified signature.
-   *
-   * @throws TypeNotFoundException if not found
-   */
-  Type getType(TypeSignature signature) throws TypeNotFoundException;
-
-  /** Gets a type given it's SQL representation */
-  Type fromSqlType(String type);
-
-  /** Gets the type with the give (opaque) id */
-  Type getType(TypeId id);
+public class InterpretedFunctionInvoker {
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/FunctionManager.java
similarity index 62%
copy from 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/FunctionManager.java
index 1830db19e19..8d8819f8f5b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/FunctionManager.java
@@ -17,21 +17,16 @@
  * under the License.
  */
 
-package org.apache.iotdb.db.queryengine.plan.relational.type;
+package org.apache.iotdb.db.queryengine.plan.relational.metadata;
 
-import org.apache.tsfile.read.common.type.Type;
+import static java.util.Objects.requireNonNull;
 
-public interface TypeManager {
-  /**
-   * Gets the type with the specified signature.
-   *
-   * @throws TypeNotFoundException if not found
-   */
-  Type getType(TypeSignature signature) throws TypeNotFoundException;
+public class FunctionManager {
 
-  /** Gets a type given it's SQL representation */
-  Type fromSqlType(String type);
+  private final FunctionManager functionManager;
+
+  public InterpretedFunctionInvoker(FunctionManager functionManager) {
+    this.functionManager = requireNonNull(functionManager, "functionManager is 
null");
+  }
 
-  /** Gets the type with the give (opaque) id */
-  Type getType(TypeId id);
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrExpressionInterpreter.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrExpressionInterpreter.java
new file mode 100644
index 00000000000..4afe56c93c9
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrExpressionInterpreter.java
@@ -0,0 +1,93 @@
+/*
+ * 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.planner;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.iotdb.db.queryengine.common.SessionInfo;
+import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider;
+import org.apache.iotdb.db.queryengine.plan.relational.analyzer.NodeRef;
+import 
org.apache.iotdb.db.queryengine.plan.relational.function.InterpretedFunctionInvoker;
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InListExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.type.TypeCoercion;
+import org.apache.tsfile.read.common.type.Type;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+public class IrExpressionInterpreter {
+
+  private final Expression expression;
+  private final PlannerContext plannerContext;
+  private final Metadata metadata;
+  private final LiteralInterpreter literalInterpreter;
+  private final LiteralEncoder literalEncoder;
+  private final SessionInfo session;
+  private final Map<NodeRef<Expression>, Type> expressionTypes;
+  private final InterpretedFunctionInvoker functionInvoker;
+  private final TypeCoercion typeCoercion;
+
+  private final IdentityHashMap<InListExpression, Set<?>> inListCache = new 
IdentityHashMap<>();
+
+
+  public IrExpressionInterpreter(Expression expression, PlannerContext 
plannerContext, SessionInfo session, Map<NodeRef<Expression>, Type> 
expressionTypes)
+  {
+    this.expression = requireNonNull(expression, "expression is null");
+    this.plannerContext = requireNonNull(plannerContext, "plannerContext is 
null");
+    this.metadata = plannerContext.getMetadata();
+    this.literalInterpreter = new LiteralInterpreter(plannerContext, session);
+    this.literalEncoder = new LiteralEncoder(plannerContext);
+    this.session = requireNonNull(session, "session is null");
+    this.expressionTypes = ImmutableMap.copyOf(requireNonNull(expressionTypes, 
"expressionTypes is null"));
+    verify(expressionTypes.containsKey(NodeRef.of(expression)));
+    this.functionInvoker = new 
InterpretedFunctionInvoker(plannerContext.getFunctionManager());
+    this.typeCoercion = new 
TypeCoercion(plannerContext.getTypeManager()::getType);
+  }
+
+  public static Object evaluateConstantExpression(Expression expression, 
PlannerContext plannerContext, SessionInfo session)
+  {
+    Map<NodeRef<Expression>, Type> types = new 
IrTypeAnalyzer(plannerContext).getTypes(session, TypeProvider.empty(), 
expression);
+    return new IrExpressionInterpreter(expression, plannerContext, session, 
types).evaluate();
+  }
+
+  public Object evaluate()
+  {
+    Object result = new 
Visitor(false).processWithExceptionHandling(expression, null);
+    verify(!(result instanceof Expression), "Expression interpreter returned 
an unresolved expression");
+    return result;
+  }
+
+  public Object evaluate(SymbolResolver inputs)
+  {
+    Object result = new 
Visitor(false).processWithExceptionHandling(expression, inputs);
+    verify(!(result instanceof Expression), "Expression interpreter returned 
an unresolved expression");
+    return result;
+  }
+
+  public Object optimize(SymbolResolver inputs)
+  {
+    return new Visitor(true).processWithExceptionHandling(expression, inputs);
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrTypeAnalyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrTypeAnalyzer.java
new file mode 100644
index 00000000000..f9c58c5e7ef
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrTypeAnalyzer.java
@@ -0,0 +1,491 @@
+/*
+ * 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.planner;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+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.analyzer.NodeRef;
+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.OperatorNotFoundException;
+import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
+import 
org.apache.iotdb.db.queryengine.plan.relational.security.AllowAllAccessControl;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ArithmeticBinaryExpression;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ArithmeticUnaryExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BetweenPredicate;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BinaryLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BooleanLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Cast;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CoalesceExpression;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FunctionCall;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.GenericLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IfExpression;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InListExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InPredicate;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IsNotNullPredicate;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IsNullPredicate;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LogicalExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NotExpression;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullIfExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullLiteral;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SearchedCaseExpression;
+import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SimpleCaseExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SymbolReference;
+import org.apache.tsfile.read.common.type.BlobType;
+import org.apache.tsfile.read.common.type.StringType;
+import org.apache.tsfile.read.common.type.Type;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static java.lang.Math.toIntExact;
+import static java.util.Objects.requireNonNull;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureTranslator.toTypeSignature;
+import static org.apache.tsfile.read.common.type.BooleanType.BOOLEAN;
+import static org.apache.tsfile.read.common.type.DoubleType.DOUBLE;
+import static org.apache.tsfile.read.common.type.IntType.INT32;
+import static org.apache.tsfile.read.common.type.LongType.INT64;
+import static org.apache.tsfile.read.common.type.UnknownType.UNKNOWN;
+
+public class IrTypeAnalyzer {
+
+  private final PlannerContext plannerContext;
+
+  public IrTypeAnalyzer(PlannerContext plannerContext) {
+    this.plannerContext = requireNonNull(plannerContext, "plannerContext is 
null");
+  }
+
+
+  public Map<NodeRef<Expression>, Type> getTypes(SessionInfo session, 
TypeProvider inputTypes, Iterable<Expression> expressions)
+  {
+    Visitor visitor = new Visitor(plannerContext, session, inputTypes);
+
+    for (Expression expression : expressions) {
+      visitor.process(expression, new Context(ImmutableMap.of()));
+    }
+
+    return visitor.getTypes();
+  }
+
+  public Map<NodeRef<Expression>, Type> getTypes(SessionInfo session, 
TypeProvider inputTypes, Expression expression)
+  {
+    return getTypes(session, inputTypes, ImmutableList.of(expression));
+  }
+
+  public Type getType(SessionInfo session, TypeProvider inputTypes, Expression 
expression)
+  {
+    return getTypes(session, inputTypes, 
expression).get(NodeRef.of(expression));
+  }
+
+  private static class Visitor
+      extends AstVisitor<Type, Context>
+  {
+    private static final AccessControl ALLOW_ALL_ACCESS_CONTROL = new 
AllowAllAccessControl();
+
+    private final PlannerContext plannerContext;
+    private final SessionInfo session;
+    private final TypeProvider symbolTypes;
+    private final FunctionResolver functionResolver;
+
+    // Cache from SQL type name to Type; every Type in the cache has a CAST 
defined from VARCHAR
+    private final Cache<String, Type> varcharCastableTypeCache = 
buildNonEvictableCache(CacheBuilder.newBuilder().maximumSize(1000));
+
+    private final Map<NodeRef<Expression>, Type> expressionTypes = new 
LinkedHashMap<>();
+
+    public Visitor(PlannerContext plannerContext, SessionInfo session, 
TypeProvider symbolTypes)
+    {
+      this.plannerContext = requireNonNull(plannerContext, "plannerContext is 
null");
+      this.session = requireNonNull(session, "session is null");
+      this.symbolTypes = requireNonNull(symbolTypes, "symbolTypes is null");
+      this.functionResolver = 
plannerContext.getFunctionResolver(WarningCollector.NOOP);
+    }
+
+    public Map<NodeRef<Expression>, Type> getTypes()
+    {
+      return expressionTypes;
+    }
+
+    private Type setExpressionType(Expression expression, Type type)
+    {
+      requireNonNull(expression, "expression cannot be null");
+      requireNonNull(type, "type cannot be null");
+
+      expressionTypes.put(NodeRef.of(expression), type);
+      return type;
+    }
+
+    @Override
+    public Type process(Node node, Context context)
+    {
+      if (node instanceof Expression) {
+        // don't double process a node
+        Type type = expressionTypes.get(NodeRef.of(((Expression) node)));
+        if (type != null) {
+          return type;
+        }
+      }
+      return super.process(node, context);
+    }
+
+
+    @Override
+    protected Type visitSymbolReference(SymbolReference node, Context context)
+    {
+      Symbol symbol = Symbol.from(node);
+      Type type = context.getArgumentTypes().get(symbol);
+      if (type == null) {
+        type = symbolTypes.getTableModelType(symbol);
+      }
+      checkArgument(type != null, "No type for: %s", node.getName());
+      return setExpressionType(node, type);
+    }
+
+    @Override
+    protected Type visitNotExpression(NotExpression node, Context context)
+    {
+      process(node.getValue(), context);
+      return setExpressionType(node, BOOLEAN);
+    }
+
+    @Override
+    protected Type visitLogicalExpression(LogicalExpression node, Context 
context)
+    {
+      node.getTerms().forEach(term -> process(term, context));
+      return setExpressionType(node, BOOLEAN);
+    }
+
+    @Override
+    protected Type visitComparisonExpression(ComparisonExpression node, 
Context context)
+    {
+      process(node.getLeft(), context);
+      process(node.getRight(), context);
+      return setExpressionType(node, BOOLEAN);
+    }
+
+    @Override
+    protected Type visitIsNullPredicate(IsNullPredicate node, Context context)
+    {
+      process(node.getValue(), context);
+      return setExpressionType(node, BOOLEAN);
+    }
+
+    @Override
+    protected Type visitIsNotNullPredicate(IsNotNullPredicate node, Context 
context)
+    {
+      process(node.getValue(), context);
+      return setExpressionType(node, BOOLEAN);
+    }
+
+    @Override
+    protected Type visitNullIfExpression(NullIfExpression node, Context 
context)
+    {
+      Type firstType = process(node.getFirst(), context);
+      Type ignored = process(node.getSecond(), context);
+
+      // TODO:
+      //    NULLIF(v1, v2) = IF(v1 = v2, v1)
+      //    In order to compare v1 and v2, they need to have the same 
(coerced) type, but
+      //    the result of NULLIF should be the same as v1. It's currently not 
possible
+      //    to represent this in the IR, so we allow the types to be different 
for now and
+      //    rely on the execution layer to insert the necessary casts.
+
+      return setExpressionType(node, firstType);
+    }
+
+    @Override
+    protected Type visitIfExpression(IfExpression node, Context context)
+    {
+      Type conditionType = process(node.getCondition(), context);
+      checkArgument(conditionType.equals(BOOLEAN), "Condition must be boolean: 
%s", conditionType);
+
+      Type trueType = process(node.getTrueValue(), context);
+      if (node.getFalseValue().isPresent()) {
+        Type falseType = process(node.getFalseValue().get(), context);
+        checkArgument(trueType.equals(falseType), "Types must be equal: %s vs 
%s", trueType, falseType);
+      }
+
+      return setExpressionType(node, trueType);
+    }
+
+    @Override
+    protected Type visitSearchedCaseExpression(SearchedCaseExpression node, 
Context context)
+    {
+      Set<Type> resultTypes = node.getWhenClauses().stream()
+          .map(clause -> {
+            Type operandType = process(clause.getOperand(), context);
+            checkArgument(operandType.equals(BOOLEAN), "When clause operand 
must be boolean: %s", operandType);
+            return setExpressionType(clause, process(clause.getResult(), 
context));
+          })
+          .collect(Collectors.toSet());
+
+      checkArgument(resultTypes.size() == 1, "All result types must be the 
same: %s", resultTypes);
+      Type resultType = resultTypes.iterator().next();
+      node.getDefaultValue().ifPresent(defaultValue -> {
+        Type defaultType = process(defaultValue, context);
+        checkArgument(defaultType.equals(resultType), "Default result type 
must be the same as WHEN result types: %s vs %s", defaultType, resultType);
+      });
+
+      return setExpressionType(node, resultType);
+    }
+
+    @Override
+    protected Type visitSimpleCaseExpression(SimpleCaseExpression node, 
Context context)
+    {
+      Type operandType = process(node.getOperand(), context);
+
+      Set<Type> resultTypes = node.getWhenClauses().stream()
+          .map(clause -> {
+            Type clauseOperandType = process(clause.getOperand(), context);
+            checkArgument(clauseOperandType.equals(operandType), "WHEN clause 
operand type must match CASE operand type: %s vs %s", clauseOperandType, 
operandType);
+            return setExpressionType(clause, process(clause.getResult(), 
context));
+          })
+          .collect(Collectors.toSet());
+
+      checkArgument(resultTypes.size() == 1, "All result types must be the 
same: %s", resultTypes);
+      Type resultType = resultTypes.iterator().next();
+      node.getDefaultValue().ifPresent(defaultValue -> {
+        Type defaultType = process(defaultValue, context);
+        checkArgument(defaultType.equals(resultType), "Default result type 
must be the same as WHEN result types: %s vs %s", defaultType, resultType);
+      });
+
+      return setExpressionType(node, resultType);
+    }
+
+    @Override
+    protected Type visitCoalesceExpression(CoalesceExpression node, Context 
context)
+    {
+      Set<Type> types = node.getOperands().stream()
+          .map(operand -> process(operand, context))
+          .collect(Collectors.toSet());
+
+      checkArgument(types.size() == 1, "All operands must have the same type: 
%s", types);
+      return setExpressionType(node, types.iterator().next());
+    }
+
+    @Override
+    protected Type visitArithmeticUnary(ArithmeticUnaryExpression node, 
Context context)
+    {
+      return setExpressionType(node, process(node.getValue(), context));
+    }
+
+    @Override
+    protected Type visitArithmeticBinary(ArithmeticBinaryExpression node, 
Context context)
+    {
+      ImmutableList.Builder<Type> argumentTypes = ImmutableList.builder();
+      argumentTypes.add(process(node.getLeft(), context));
+      argumentTypes.add(process(node.getRight(), context));
+
+      try {
+        return setExpressionType(node, 
plannerContext.getMetadata().getOperatorReturnType(OperatorType.valueOf(node.getOperator().name()),
 argumentTypes.build()));
+      } catch (OperatorNotFoundException e) {
+        throw new SemanticException(e.getMessage());
+      }
+    }
+
+    @Override
+    protected Type visitStringLiteral(StringLiteral node, Context context)
+    {
+      return setExpressionType(node, StringType.STRING);
+    }
+
+    @Override
+    protected Type visitBinaryLiteral(BinaryLiteral node, Context context)
+    {
+      return setExpressionType(node, BlobType.BLOB);
+    }
+
+    @Override
+    protected Type visitLongLiteral(LongLiteral node, Context context)
+    {
+      if (node.getParsedValue() >= Integer.MIN_VALUE && node.getParsedValue() 
<= Integer.MAX_VALUE) {
+        return setExpressionType(node, INT32);
+      }
+
+      return setExpressionType(node, INT64);
+    }
+
+    @Override
+    protected Type visitDoubleLiteral(DoubleLiteral node, Context context)
+    {
+      return setExpressionType(node, DOUBLE);
+    }
+
+    @Override
+    protected Type visitBooleanLiteral(BooleanLiteral node, Context context)
+    {
+      return setExpressionType(node, BOOLEAN);
+    }
+
+    @Override
+    protected Type visitGenericLiteral(GenericLiteral node, Context context)
+    {
+      return setExpressionType(
+          node,
+          switch (node.getType()) {
+            case String name when name.equalsIgnoreCase("CHAR") -> 
CharType.createCharType(node.getValue().length());
+            case String name when name.equalsIgnoreCase("TIMESTAMP") && 
timestampHasTimeZone(node.getValue()) -> 
createTimestampWithTimeZoneType(extractTimestampPrecision(node.getValue()));
+            case String name when name.equalsIgnoreCase("TIMESTAMP") -> 
createTimestampType(extractTimestampPrecision(node.getValue()));
+            case String name when name.equalsIgnoreCase("TIME") && 
timeHasTimeZone(node.getValue()) -> 
createTimeWithTimeZoneType(extractTimePrecision(node.getValue()));
+            case String name when name.equalsIgnoreCase("TIME") -> 
createTimeType(extractTimePrecision(node.getValue()));
+            default -> uncheckedCacheGet(varcharCastableTypeCache, 
node.getType(), () -> 
plannerContext.getTypeManager().fromSqlType(node.getType()));
+          });
+    }
+
+    @Override
+    protected Type visitNullLiteral(NullLiteral node, Context context)
+    {
+      return setExpressionType(node, UNKNOWN);
+    }
+
+    @Override
+    protected Type visitFunctionCall(FunctionCall node, Context context)
+    {
+      // Function should already be resolved in IR
+      ResolvedFunction function = functionResolver.resolveFunction(session, 
node.getName(), null, ALLOW_ALL_ACCESS_CONTROL);
+
+      BoundSignature signature = function.getSignature();
+      for (int i = 0; i < node.getArguments().size(); i++) {
+        Expression argument = node.getArguments().get(i);
+        Type formalType = signature.getArgumentTypes().get(i);
+
+        Type unused = switch (argument) {
+          case LambdaExpression lambda -> processLambdaExpression(lambda, 
((FunctionType) formalType).getArgumentTypes());
+          case BindExpression bind -> processBindExpression(bind, 
(FunctionType) formalType, context);
+          default -> process(argument, context);
+        };
+
+        // TODO
+        // checkArgument(actualType.equals(formalType), "Actual and formal 
argument types do not match: %s vs %s", actualType, formalType);
+      }
+
+      return setExpressionType(node, signature.getReturnType());
+    }
+
+    private Type processBindExpression(BindExpression bind, FunctionType 
formalType, Context context)
+    {
+      List<Type> argumentTypes = new ArrayList<>();
+
+      argumentTypes.addAll(bind.getValues().stream()
+          .map(value -> process(value, context))
+          .collect(toImmutableList()));
+
+      argumentTypes.addAll(formalType.getArgumentTypes());
+
+      if (bind.getFunction() instanceof LambdaExpression) {
+        Type unused = processLambdaExpression((LambdaExpression) 
bind.getFunction(), argumentTypes);
+        // TODO: validate actual type and expected type are the same
+        return setExpressionType(bind, formalType);
+      }
+
+      throw new UnsupportedOperationException("not yet implemented");
+    }
+
+    private Type processLambdaExpression(LambdaExpression lambda, List<Type> 
argumentTypes)
+    {
+      ImmutableMap.Builder<Symbol, Type> typeBindings = ImmutableMap.builder();
+      for (int i = 0; i < argumentTypes.size(); i++) {
+        typeBindings.put(
+            new Symbol(lambda.getArguments().get(i).getName().getValue()),
+            argumentTypes.get(i));
+      }
+
+      Type returnType = process(lambda.getBody(), new 
Context(typeBindings.buildOrThrow()));
+      return setExpressionType(lambda, new FunctionType(argumentTypes, 
returnType));
+    }
+
+    @Override
+    protected Type visitBetweenPredicate(BetweenPredicate node, Context 
context)
+    {
+      process(node.getValue(), context);
+      process(node.getMin(), context);
+      process(node.getMax(), context);
+
+      return setExpressionType(node, BOOLEAN);
+    }
+
+    @Override
+    public Type visitCast(Cast node, Context context)
+    {
+      process(node.getExpression(), context);
+      return setExpressionType(node, 
plannerContext.getTypeManager().getType(toTypeSignature(node.getType())));
+    }
+
+    @Override
+    protected Type visitInPredicate(InPredicate node, Context context)
+    {
+      Expression value = node.getValue();
+      InListExpression valueList = (InListExpression) node.getValueList();
+
+      Type type = process(value, context);
+      for (Expression item : valueList.getValues()) {
+        Type itemType = process(item, context);
+        checkArgument(itemType.equals(type), "Types must be equal: %s vs %s", 
itemType, type);
+      }
+
+      setExpressionType(valueList, type);
+
+      return setExpressionType(node, BOOLEAN);
+    }
+
+    @Override
+    protected Type visitExpression(Expression node, Context context)
+    {
+      throw new UnsupportedOperationException("Not a valid IR expression: " + 
node.getClass().getName());
+    }
+
+    @Override
+    protected Type visitNode(Node node, Context context)
+    {
+      throw new UnsupportedOperationException("Not a valid IR expression: " + 
node.getClass().getName());
+    }
+  }
+
+  private static class Context {
+    private final Map<Symbol, Type> argumentTypes;
+
+    public Context(Map<Symbol, Type> argumentTypes) {
+      this.argumentTypes = argumentTypes;
+    }
+
+    public Map<Symbol, Type> getArgumentTypes() {
+      return argumentTypes;
+    }
+  }
+
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralEncoder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralEncoder.java
new file mode 100644
index 00000000000..c8d88f66be8
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralEncoder.java
@@ -0,0 +1,126 @@
+/*
+ * 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.planner;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BinaryLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BooleanLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Cast;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.GenericLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral;
+import org.apache.tsfile.common.conf.TSFileConfig;
+import org.apache.tsfile.read.common.type.DateType;
+import org.apache.tsfile.read.common.type.TimestampType;
+import org.apache.tsfile.read.common.type.Type;
+import org.apache.tsfile.read.common.type.UnknownType;
+import org.apache.tsfile.utils.Binary;
+
+import java.util.List;
+import javax.annotation.Nullable;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl.isBlobType;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl.isBool;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl.isCharType;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureTranslator.toSqlType;
+import static org.apache.tsfile.read.common.type.DoubleType.DOUBLE;
+import static org.apache.tsfile.read.common.type.FloatType.FLOAT;
+import static org.apache.tsfile.read.common.type.IntType.INT32;
+import static org.apache.tsfile.read.common.type.LongType.INT64;
+
+public final class LiteralEncoder {
+
+  private final PlannerContext plannerContext;
+
+  public LiteralEncoder(PlannerContext plannerContext) {
+    this.plannerContext = requireNonNull(plannerContext, "plannerContext is 
null");
+  }
+
+  public List<Expression> toExpressions(List<?> objects, List<? extends Type> 
types) {
+    requireNonNull(objects, "objects is null");
+    requireNonNull(types, "types is null");
+    checkArgument(objects.size() == types.size(), "objects and types do not 
have the same size");
+
+    ImmutableList.Builder<Expression> expressions = ImmutableList.builder();
+    for (int i = 0; i < objects.size(); i++) {
+      Object object = objects.get(i);
+      Type type = types.get(i);
+      expressions.add(toExpression(object, type));
+    }
+    return expressions.build();
+  }
+
+  public Expression toExpression(@Nullable Object object, Type type) {
+    requireNonNull(type, "type is null");
+
+    if (object instanceof Expression) {
+      return (Expression) object;
+    }
+
+    if (object == null) {
+      if (type.equals(UnknownType.UNKNOWN)) {
+        return new NullLiteral();
+      }
+      return new Cast(new NullLiteral(), toSqlType(type), false);
+    }
+
+
+    if (type.equals(INT32) || type.equals(INT64)) {
+      return new LongLiteral(object.toString());
+    }
+
+
+    if (type.equals(FLOAT) || type.equals(DOUBLE)) {
+      Double value = (Double) object;
+      return new DoubleLiteral(value);
+    }
+
+    if (isBool(type)) {
+      return new BooleanLiteral(object.toString());
+    }
+
+    if (isCharType(type)) {
+      Binary value = (Binary) object;
+      return new 
StringLiteral(value.getStringValue(TSFileConfig.STRING_CHARSET));
+    }
+
+    if (isBlobType(type)) {
+      Binary value = (Binary) object;
+      return new BinaryLiteral(value.getValues());
+    }
+
+
+    if (type.equals(DateType.DATE)) {
+      return new GenericLiteral(DateType.DATE.getTypeEnum().name(), ((Integer) 
object).toString());
+    }
+
+    if (type.equals(TimestampType.TIMESTAMP)) {
+      return new GenericLiteral(TimestampType.TIMESTAMP.getTypeEnum().name(), 
object.toString());
+    }
+
+    throw new IllegalArgumentException("Unknown type: " + type);
+  }
+
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralInterpreter.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralInterpreter.java
new file mode 100644
index 00000000000..0e2e5936129
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralInterpreter.java
@@ -0,0 +1,112 @@
+/*
+ * 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.planner;
+
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.queryengine.common.SessionInfo;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BinaryLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BooleanLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.GenericLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Literal;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral;
+import org.apache.tsfile.common.conf.TSFileConfig;
+import org.apache.tsfile.read.common.type.DateType;
+import org.apache.tsfile.read.common.type.TimestampType;
+import org.apache.tsfile.read.common.type.Type;
+import org.apache.tsfile.utils.Binary;
+
+import static java.util.Objects.requireNonNull;
+
+public class LiteralInterpreter {
+
+  private final PlannerContext plannerContext;
+  private final SessionInfo session;
+
+  public LiteralInterpreter(PlannerContext plannerContext, SessionInfo 
session) {
+    this.plannerContext = requireNonNull(plannerContext, "plannerContext is 
null");
+    this.session = session;
+  }
+
+  public Object evaluate(Expression node, Type type) {
+    if (!(node instanceof Literal)) {
+      throw new IllegalArgumentException("node must be a Literal");
+    }
+    return new LiteralVisitor(type).process(node, null);
+  }
+
+  private class LiteralVisitor extends AstVisitor<Object, Void> {
+    private final Type type;
+
+    private LiteralVisitor(Type type) {
+      this.type = requireNonNull(type, "type is null");
+    }
+
+    @Override
+    protected Object visitLiteral(Literal node, Void context) {
+      throw new UnsupportedOperationException("Unhandled literal type: " + 
node);
+    }
+
+    @Override
+    protected Object visitBooleanLiteral(BooleanLiteral node, Void context) {
+      return node.getValue();
+    }
+
+    @Override
+    protected Long visitLongLiteral(LongLiteral node, Void context) {
+      return node.getParsedValue();
+    }
+
+    @Override
+    protected Double visitDoubleLiteral(DoubleLiteral node, Void context) {
+      return node.getValue();
+    }
+
+    @Override
+    protected Binary visitStringLiteral(StringLiteral node, Void context) {
+      return new Binary(node.getValue(), TSFileConfig.STRING_CHARSET);
+    }
+
+    @Override
+    protected Binary visitBinaryLiteral(BinaryLiteral node, Void context) {
+      return new Binary(node.getValue());
+    }
+
+    @Override
+    protected Object visitGenericLiteral(GenericLiteral node, Void context) {
+      if (type.equals(TimestampType.TIMESTAMP)) {
+        return Long.parseLong(node.getValue());
+      } else if (type.equals(DateType.DATE)) {
+        return Integer.parseInt(node.getValue());
+      } else {
+        throw new SemanticException(String.format("No literal form for type 
%s", type));
+      }
+    }
+
+    @Override
+    protected Object visitNullLiteral(NullLiteral node, Void context) {
+      return null;
+    }
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java
index 7fb3a2cb59e..094d417a74b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java
@@ -41,4 +41,8 @@ public class PlannerContext {
   public Metadata getMetadata() {
     return metadata;
   }
+
+  public TypeManager getTypeManager() {
+    return typeManager;
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java
similarity index 62%
copy from 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java
index 1830db19e19..947d553c508 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java
@@ -17,21 +17,7 @@
  * under the License.
  */
 
-package org.apache.iotdb.db.queryengine.plan.relational.type;
+package org.apache.iotdb.db.queryengine.plan.relational.security;
 
-import org.apache.tsfile.read.common.type.Type;
-
-public interface TypeManager {
-  /**
-   * Gets the type with the specified signature.
-   *
-   * @throws TypeNotFoundException if not found
-   */
-  Type getType(TypeSignature signature) throws TypeNotFoundException;
-
-  /** Gets a type given it's SQL representation */
-  Type fromSqlType(String type);
-
-  /** Gets the type with the give (opaque) id */
-  Type getType(TypeId id);
+public class AllowAllAccessControl implements AccessControl {
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/BinaryLiteral.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/BinaryLiteral.java
index 22aa5c8107b..c7011205960 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/BinaryLiteral.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/BinaryLiteral.java
@@ -55,6 +55,15 @@ public class BinaryLiteral extends Literal {
     this.value = BaseEncoding.base16().decode(hexString);
   }
 
+  public BinaryLiteral(byte[] value) {
+    super(null);
+    requireNonNull(value, "value is null");
+    if (value.length % 2 != 0) {
+      throw new ParsingException("Binary literal must contain an even number 
of digits");
+    }
+    this.value = value;
+  }
+
   public BinaryLiteral(NodeLocation location, String value) {
     super(requireNonNull(location, "location is null"));
     requireNonNull(value, "value is null");
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DoubleLiteral.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DoubleLiteral.java
index d7916148a6c..cf2fa708326 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DoubleLiteral.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DoubleLiteral.java
@@ -36,6 +36,11 @@ public class DoubleLiteral extends Literal {
     this.value = Double.parseDouble(requireNonNull(value, "value is null"));
   }
 
+  public DoubleLiteral(double value) {
+    super(null);
+    this.value = value;
+  }
+
   public DoubleLiteral(NodeLocation location, String value) {
     super(requireNonNull(location, "location is null"));
     this.value = Double.parseDouble(requireNonNull(value, "value is null"));
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeCoercion.java
similarity index 71%
copy from 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeCoercion.java
index 1830db19e19..f6105f579b1 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeCoercion.java
@@ -21,17 +21,15 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.type;
 
 import org.apache.tsfile.read.common.type.Type;
 
-public interface TypeManager {
-  /**
-   * Gets the type with the specified signature.
-   *
-   * @throws TypeNotFoundException if not found
-   */
-  Type getType(TypeSignature signature) throws TypeNotFoundException;
+import java.util.function.Function;
 
-  /** Gets a type given it's SQL representation */
-  Type fromSqlType(String type);
+import static java.util.Objects.requireNonNull;
+
+public class TypeCoercion {
+  private final Function<TypeSignature, Type> lookupType;
+
+  public TypeCoercion(Function<TypeSignature, Type> lookupType) {
+    this.lookupType = requireNonNull(lookupType, "lookupType is null");
+  }
 
-  /** Gets the type with the give (opaque) id */
-  Type getType(TypeId id);
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
index 1830db19e19..a39947aa4d3 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java
@@ -27,7 +27,7 @@ public interface TypeManager {
    *
    * @throws TypeNotFoundException if not found
    */
-  Type getType(TypeSignature signature) throws TypeNotFoundException;
+  Type getType(TypeSignature signature);
 
   /** Gets a type given it's SQL representation */
   Type fromSqlType(String type);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java
index 20d7281abf8..99df1101bda 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java
@@ -19,12 +19,12 @@
 
 package org.apache.iotdb.db.queryengine.plan.relational.type;
 
-import org.apache.iotdb.commons.exception.IoTDBException;
+import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
 
 import static java.util.Objects.requireNonNull;
 import static org.apache.iotdb.rpc.TSStatusCode.TYPE_NOT_FOUND;
 
-public class TypeNotFoundException extends IoTDBException {
+public class TypeNotFoundException extends IoTDBRuntimeException {
 
   private final TypeSignature 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
index 6cfcc5d81a8..03eff294b31 100644
--- 
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
@@ -28,9 +28,11 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NumericParameter;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.TypeParameter;
 
 import com.google.common.collect.ImmutableList;
+import org.apache.tsfile.read.common.type.Type;
 
 import java.util.Collections;
 import java.util.Locale;
+import java.util.Optional;
 import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -42,6 +44,11 @@ public class TypeSignatureTranslator {
 
   private TypeSignatureTranslator() {}
 
+  public static DataType toSqlType(Type type)
+  {
+    return new GenericDataType(new Identifier(type.getTypeEnum().name(), 
false), Collections.emptyList());
+  }
+
   public static TypeSignature toTypeSignature(DataType type) {
     return toTypeSignature(type, Collections.emptySet());
   }

Reply via email to