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

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


The following commit(s) were added to refs/heads/master by this push:
     new 512718f629 [enhancement](Nereids)(planner) fix some problem in Nereids 
and legacy planner (#18280)
512718f629 is described below

commit 512718f629bd71b9bbb7249460dc3ad52951799a
Author: morrySnow <101034200+morrys...@users.noreply.github.com>
AuthorDate: Mon Apr 10 18:25:33 2023 +0800

    [enhancement](Nereids)(planner) fix some problem in Nereids and legacy 
planner (#18280)
    
    1. remove TypeCoercion and CharacterLiteralTypeCoercion
    2. Nereids Cast do not relay on legacy planner's analyze()
    3. fix below problem in legacy planner, after this PR
        a. BOOLEAN can cast to DECIMALV2 explicitly
        b. compare between BOOLEAN and DATE will cast both side to DOUBLE
        c. HLL cannot be implicitly cast to any other type
---
 .../main/java/org/apache/doris/catalog/Type.java   |   8 +-
 .../java/org/apache/doris/analysis/CastExpr.java   |  83 ++++++---
 .../main/java/org/apache/doris/analysis/Expr.java  |  72 ++++----
 .../jobs/batch/CheckLegalityAfterRewrite.java      |   4 +-
 .../batch/CheckLegalityBeforeTypeCoercion.java     |   4 +-
 .../doris/nereids/jobs/batch/NereidsRewriter.java  |   6 +-
 .../nereids/rules/analysis/BindExpression.java     |  12 +-
 .../ResolveOrdinalInOrderByAndGroupBy.java         |   4 +-
 .../AbstractExpressionRewriteRule.java             |   2 +-
 .../{rewrite => }/ExpressionNormalization.java     |  33 ++--
 .../{rewrite => }/ExpressionOptimization.java      |  10 +-
 .../{rewrite => }/ExpressionRewrite.java           |   2 +-
 .../{rewrite => }/ExpressionRewriteContext.java    |   7 +-
 .../{rewrite => }/ExpressionRewriteRule.java       |   2 +-
 .../{rewrite => }/ExpressionRuleExecutor.java      |   4 +-
 .../nereids/rules/expression/check/CheckCast.java  |  89 +++++++++
 .../rules/CharacterLiteralTypeCoercion.java        |  43 -----
 .../expression/rewrite/rules/TypeCoercion.java     | 164 -----------------
 .../{rewrite => }/rules/BetweenToCompoundRule.java |  13 +-
 .../{rewrite => }/rules/ColumnBound.java           |   2 +-
 .../{rewrite => }/rules/ColumnRange.java           |   2 +-
 .../{rewrite => }/rules/DigitalMaskingConvert.java |   6 +-
 .../rules/DistinctPredicatesRule.java              |   6 +-
 .../rules/ExtractCommonFactorRule.java             |   6 +-
 .../{rewrite => }/rules/FoldConstantRule.java      |  10 +-
 .../{rewrite => }/rules/FoldConstantRuleOnBE.java  |   8 +-
 .../{rewrite => }/rules/FoldConstantRuleOnFE.java  |  16 +-
 .../rules}/FunctionBinder.java                     |  43 ++---
 .../{rewrite => }/rules/InPredicateDedup.java      |   6 +-
 .../rules/InPredicateToEqualToRule.java            |   6 +-
 .../rules/NormalizeBinaryPredicatesRule.java       |   6 +-
 .../rules/OneListPartitionEvaluator.java           |   4 +-
 .../{rewrite => }/rules/OnePartitionEvaluator.java |   2 +-
 .../rules/OneRangePartitionEvaluator.java          |  10 +-
 .../{rewrite => }/rules/PartitionPruner.java       |   2 +-
 .../rules/PartitionRangeExpander.java              |   2 +-
 .../{rewrite => }/rules/PartitionSlotInput.java    |   2 +-
 .../rules/SimplifyArithmeticComparisonRule.java    |  15 +-
 .../rules/SimplifyArithmeticRule.java              |   6 +-
 .../{rewrite => }/rules/SimplifyCastRule.java      |   7 +-
 .../rules/SimplifyComparisonPredicate.java         |   6 +-
 .../{rewrite => }/rules/SimplifyNotExprRule.java   |   6 +-
 .../{rewrite => }/rules/SimplifyRange.java         |   8 +-
 .../rules/SupportJavaDateFormatter.java            |   6 +-
 .../rules/TryEliminateUninterestedPredicates.java  |   6 +-
 .../rules/UnknownPartitionEvaluator.java           |   2 +-
 .../rules/implementation/AggregateStrategies.java  |   8 +-
 .../rewrite/logical/EliminateGroupByConstant.java  |   4 +-
 .../rewrite/logical/PruneOlapScanPartition.java    |   2 +-
 .../doris/nereids/trees/expressions/Divide.java    |   4 +-
 .../doris/nereids/trees/expressions/Multiply.java  |   2 +-
 .../functions/scalar/DigitalMasking.java           |   3 +-
 .../nereids/trees/expressions/literal/Literal.java |   2 +-
 .../trees/expressions/literal/NullLiteral.java     |   2 -
 .../org/apache/doris/nereids/types/DataType.java   |  14 +-
 .../apache/doris/nereids/util/ExpressionUtils.java |   6 +-
 .../doris/nereids/util/TypeCoercionUtils.java      |   2 +-
 .../analysis/CheckExpressionLegalityTest.java      |   2 +-
 .../rules/analysis/FillUpMissingSlotsTest.java     |  10 +-
 .../{rewrite => }/ExpressionRewriteTest.java       |  22 +--
 .../{rewrite => }/ExpressionRewriteTestHelper.java |   6 +-
 .../expression/{rewrite => }/FoldConstantTest.java |   4 +-
 .../{rewrite => }/SimplifyArithmeticRuleTest.java  |  14 +-
 .../{rewrite => }/SimplifyRangeTest.java           |   4 +-
 .../rules/expression/rewrite/TypeCoercionTest.java | 204 ---------------------
 65 files changed, 395 insertions(+), 683 deletions(-)

diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
index 5e794b27e0..48037297aa 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
@@ -1706,15 +1706,15 @@ public abstract class Type {
         }
 
         // int family type and char family type should cast to char family type
-        if ((t1ResultType.isFixedPointType() && t2ResultType.isCharFamily())
-                || (t2ResultType.isFixedPointType() && 
t1ResultType.isCharFamily())) {
-            return t1.isStringType() ? t1 : t2;
+        if ((t1.getPrimitiveType().isFixedPointType() && 
t2.getPrimitiveType().isCharFamily())
+                || (t2.getPrimitiveType().isFixedPointType() && 
t1.getPrimitiveType().isCharFamily())) {
+            return Type.VARCHAR;
         }
 
         if (t1ResultType == PrimitiveType.BIGINT && t2ResultType == 
PrimitiveType.BIGINT) {
             return getAssignmentCompatibleType(t1, t2, false);
         }
-        if (t1ResultType.isDecimalV3Type() && t2ResultType.isDecimalV3Type()) {
+        if (t1.getPrimitiveType().isDecimalV3Type() && 
t2.getPrimitiveType().isDecimalV3Type()) {
             int resultPrecision = Math.max(t1.getPrecision(), 
t2.getPrecision());
             PrimitiveType resultDecimalType;
             if (resultPrecision <= ScalarType.MAX_DECIMAL32_PRECISION) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java
index a59f30039d..b2779c33cf 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java
@@ -22,6 +22,7 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.Function;
+import org.apache.doris.catalog.Function.NullableMode;
 import org.apache.doris.catalog.FunctionSet;
 import org.apache.doris.catalog.PrimitiveType;
 import org.apache.doris.catalog.ScalarFunction;
@@ -71,7 +72,7 @@ public class CastExpr extends Expr {
                 continue;
             }
             for (ScalarType toType : Type.getSupportedTypes()) {
-                if (fromType.isNull()) {
+                if (toType.isNull()) {
                     continue;
                 }
                 if (fromType.isStringType() && !toType.isStringType()) {
@@ -116,17 +117,39 @@ public class CastExpr extends Expr {
     public CastExpr(Type targetType, Expr e, Void v) {
         Preconditions.checkArgument(targetType.isValid());
         Preconditions.checkNotNull(e);
+        opcode = TExprOpcode.CAST;
         type = targetType;
         targetTypeDef = null;
         isImplicit = true;
         children.add(e);
-        try {
-            analyze();
-        } catch (AnalysisException ex) {
-            LOG.warn("Implicit casts fail", ex);
-            Preconditions.checkState(false,
-                    "Implicit casts should never throw analysis exception.");
+
+        noOp = Type.matchExactType(e.type, type, true);
+        if (noOp) {
+            // For decimalv2, we do not perform an actual cast between 
different precision/scale. Instead, we just
+            // set the target type as the child's type.
+            if (type.isDecimalV2() && e.type.isDecimalV2()) {
+                getChild(0).setType(type);
+            }
+            return;
         }
+
+        if (e.type.isNull()) {
+            return;
+        }
+
+        // new function
+        if (type.isScalarType()) {
+            Type from = getActualArgTypes(collectChildReturnTypes())[0];
+            Type to = getActualType(type);
+            NullableMode nullableMode = TYPE_NULLABLE_MODE.get(Pair.of(from, 
to));
+            Preconditions.checkState(nullableMode != null,
+                    "cannot find nullable node for cast from " + from + " to " 
+ to);
+            fn = new Function(new FunctionName(getFnName(type)), 
Lists.newArrayList(e.type), type,
+                    false, true, nullableMode);
+        } else {
+            createComplexTypeCastFunction();
+        }
+
         analysisDone();
     }
 
@@ -158,7 +181,7 @@ public class CastExpr extends Expr {
 
     private static boolean disableRegisterCastingFunction(Type fromType, Type 
toType) {
         // Disable casting from boolean to decimal or datetime or date
-        if (fromType.isBoolean() && (toType.equals(Type.DECIMALV2) || 
toType.isDateType())) {
+        if (fromType.isBoolean() && toType.isDateType()) {
             return true;
         }
 
@@ -279,6 +302,25 @@ public class CastExpr extends Expr {
         isImplicit = implicit;
     }
 
+    private void createComplexTypeCastFunction() {
+        if (type.isArrayType()) {
+            fn = ScalarFunction.createBuiltin(getFnName(Type.ARRAY),
+                    type, Function.NullableMode.ALWAYS_NULLABLE,
+                    Lists.newArrayList(Type.VARCHAR), false,
+                    "doris::CastFunctions::cast_to_array_val", null, null, 
true);
+        } else if (type.isMapType()) {
+            fn = ScalarFunction.createBuiltin(getFnName(Type.MAP),
+                    type, Function.NullableMode.ALWAYS_NULLABLE,
+                    Lists.newArrayList(Type.VARCHAR), false,
+                    "doris::CastFunctions::cast_to_map_val", null, null, true);
+        } else if (type.isStructType()) {
+            fn = ScalarFunction.createBuiltin(getFnName(Type.STRUCT),
+                    type, Function.NullableMode.ALWAYS_NULLABLE,
+                    Lists.newArrayList(Type.VARCHAR), false,
+                    "doris::CastFunctions::cast_to_struct_val", null, null, 
true);
+        }
+    }
+
     public void analyze() throws AnalysisException {
         // do not analyze ALL cast
         if (type == Type.ALL) {
@@ -314,28 +356,9 @@ public class CastExpr extends Expr {
         Function searchDesc = new Function(fnName, 
Arrays.asList(getActualArgTypes(collectChildReturnTypes())),
                 Type.INVALID, false);
         if (type.isScalarType()) {
-            if (isImplicit) {
-                fn = Env.getCurrentEnv().getFunction(
-                        searchDesc, 
Function.CompareMode.IS_NONSTRICT_SUPERTYPE_OF);
-            } else {
-                fn = Env.getCurrentEnv().getFunction(
-                        searchDesc, Function.CompareMode.IS_IDENTICAL);
-            }
-        } else if (type.isArrayType()) {
-            fn = ScalarFunction.createBuiltin(getFnName(Type.ARRAY),
-                    type, Function.NullableMode.ALWAYS_NULLABLE,
-                    Lists.newArrayList(Type.VARCHAR), false,
-                    "doris::CastFunctions::cast_to_array_val", null, null, 
true);
-        } else if (type.isMapType()) {
-            fn = ScalarFunction.createBuiltin(getFnName(Type.MAP),
-                type, Function.NullableMode.ALWAYS_NULLABLE,
-                Lists.newArrayList(Type.VARCHAR), false,
-                "doris::CastFunctions::cast_to_map_val", null, null, true);
-        } else if (type.isStructType()) {
-            fn = ScalarFunction.createBuiltin(getFnName(Type.STRUCT),
-                    type, Function.NullableMode.ALWAYS_NULLABLE,
-                    Lists.newArrayList(Type.VARCHAR), false,
-                    "doris::CastFunctions::cast_to_struct_val", null, null, 
true);
+            fn = Env.getCurrentEnv().getFunction(searchDesc, 
Function.CompareMode.IS_IDENTICAL);
+        } else {
+            createComplexTypeCastFunction();
         }
 
         if (fn == null) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
index f59994f8a5..ab8d7e3e45 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
@@ -1431,8 +1431,7 @@ public abstract class Expr extends TreeNode<Expr> 
implements ParseNode, Cloneabl
             return this;
         }
 
-        if ((targetType.isStringType() || targetType.isHllType())
-                && (this.type.isStringType() || this.type.isHllType())) {
+        if (this.type.equals(targetType)) {
             return this;
         }
 
@@ -1442,6 +1441,10 @@ public abstract class Expr extends TreeNode<Expr> 
implements ParseNode, Cloneabl
             return this;
         }
 
+        if (this.type.isStringType() && targetType.isStringType()) {
+            return this;
+        }
+
         // Preconditions.checkState(PrimitiveType.isImplicitCast(type, 
targetType),
         // "cast %s to %s", this.type, targetType);
         // TODO(zc): use implicit cast
@@ -2253,41 +2256,44 @@ public abstract class Expr extends TreeNode<Expr> 
implements ParseNode, Cloneabl
         return this;
     }
 
+    protected Type getActualType(Type originType) {
+        if (originType == null) {
+            return null;
+        }
+        if (originType.isScalarType()) {
+            return getActualScalarType(originType);
+        } else if (originType.getPrimitiveType() == PrimitiveType.ARRAY) {
+            return getActualArrayType((ArrayType) originType);
+        } else {
+            return originType;
+        }
+    }
+
+    protected  Type getActualScalarType(Type originType) {
+        if (originType.getPrimitiveType() == PrimitiveType.DECIMAL32) {
+            return Type.DECIMAL32;
+        } else if (originType.getPrimitiveType() == PrimitiveType.DECIMAL64) {
+            return Type.DECIMAL64;
+        } else if (originType.getPrimitiveType() == PrimitiveType.DECIMAL128) {
+            return Type.DECIMAL128;
+        } else if (originType.getPrimitiveType() == PrimitiveType.DATETIMEV2) {
+            return Type.DATETIMEV2;
+        } else if (originType.getPrimitiveType() == PrimitiveType.VARCHAR) {
+            return Type.VARCHAR;
+        } else if (originType.getPrimitiveType() == PrimitiveType.CHAR) {
+            return Type.CHAR;
+        } else if (originType.getPrimitiveType() == PrimitiveType.DECIMALV2) {
+            return Type.MAX_DECIMALV2_TYPE;
+        }
+        return originType;
+    }
+
     protected Type[] getActualArgTypes(Type[] originType) {
-        return Arrays.stream(originType).map(
-                (Type type) -> {
-                    if (type == null) {
-                        return null;
-                    }
-                    if (type.getPrimitiveType() == PrimitiveType.DECIMAL32) {
-                        return Type.DECIMAL32;
-                    } else if (type.getPrimitiveType() == 
PrimitiveType.DECIMAL64) {
-                        return Type.DECIMAL64;
-                    } else if (type.getPrimitiveType() == 
PrimitiveType.DECIMAL128) {
-                        return Type.DECIMAL128;
-                    } else if (type.getPrimitiveType() == 
PrimitiveType.DATETIMEV2) {
-                        return Type.DATETIMEV2;
-                    } else if (type.getPrimitiveType() == PrimitiveType.ARRAY) 
{
-                        return getActualArrayType((ArrayType) type);
-                    }
-                    return type;
-                }).toArray(Type[]::new);
+        return 
Arrays.stream(originType).map(this::getActualType).toArray(Type[]::new);
     }
 
     private ArrayType getActualArrayType(ArrayType originArrayType) {
-        // Now we only support single-level array nesting.
-        // Multi-layer array nesting will be supported in the future.
-        Type type = originArrayType.getItemType();
-        if (type.getPrimitiveType() == PrimitiveType.DECIMAL32) {
-            return new ArrayType(Type.DECIMAL32);
-        } else if (type.getPrimitiveType() == PrimitiveType.DECIMAL64) {
-            return new ArrayType(Type.DECIMAL64);
-        } else if (type.getPrimitiveType() == PrimitiveType.DECIMAL128) {
-            return new ArrayType(Type.DECIMAL128);
-        } else if (type.getPrimitiveType() == PrimitiveType.DATETIMEV2) {
-            return new ArrayType(Type.DATETIMEV2);
-        }
-        return originArrayType;
+        return new ArrayType(getActualType(originArrayType.getItemType()));
     }
 
     public boolean refToCountStar() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/CheckLegalityAfterRewrite.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/CheckLegalityAfterRewrite.java
index 53d6e17d87..dbe3b1f5a0 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/CheckLegalityAfterRewrite.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/CheckLegalityAfterRewrite.java
@@ -17,8 +17,8 @@
 
 package org.apache.doris.nereids.jobs.batch;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Expression;
 
 /** CheckLegalityAfterRewrite */
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/CheckLegalityBeforeTypeCoercion.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/CheckLegalityBeforeTypeCoercion.java
index b27d914b6f..a82cc6b78e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/CheckLegalityBeforeTypeCoercion.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/CheckLegalityBeforeTypeCoercion.java
@@ -17,8 +17,8 @@
 
 package org.apache.doris.nereids.jobs.batch;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Expression;
 
 /** CheckLegalityBeforeTypeCoercion */
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/NereidsRewriter.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/NereidsRewriter.java
index 379cc4bd5a..cff1d447ed 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/NereidsRewriter.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/NereidsRewriter.java
@@ -26,9 +26,9 @@ import 
org.apache.doris.nereids.rules.analysis.AdjustAggregateNullableForEmptySe
 import org.apache.doris.nereids.rules.analysis.AvgDistinctToSumDivCount;
 import org.apache.doris.nereids.rules.analysis.CheckAfterRewrite;
 import 
org.apache.doris.nereids.rules.analysis.LogicalSubQueryAliasToLogicalProject;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionNormalization;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionOptimization;
-import org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewrite;
+import org.apache.doris.nereids.rules.expression.ExpressionNormalization;
+import org.apache.doris.nereids.rules.expression.ExpressionOptimization;
+import org.apache.doris.nereids.rules.expression.ExpressionRewrite;
 import org.apache.doris.nereids.rules.mv.SelectMaterializedIndexWithAggregate;
 import 
org.apache.doris.nereids.rules.mv.SelectMaterializedIndexWithoutAggregate;
 import org.apache.doris.nereids.rules.rewrite.logical.AdjustNullable;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
index 6e74cc1dbf..f8f561cc52 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
@@ -31,7 +31,8 @@ import org.apache.doris.nereids.properties.OrderKey;
 import 
org.apache.doris.nereids.rules.AppliedAwareRule.AppliedAwareRuleCondition;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
-import org.apache.doris.nereids.rules.expression.rewrite.rules.TypeCoercion;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.rules.FunctionBinder;
 import org.apache.doris.nereids.trees.UnaryNode;
 import org.apache.doris.nereids.trees.expressions.Alias;
 import org.apache.doris.nereids.trees.expressions.BoundStar;
@@ -66,6 +67,7 @@ import 
org.apache.doris.nereids.trees.plans.logical.LogicalSetOperation;
 import org.apache.doris.nereids.trees.plans.logical.LogicalSort;
 import org.apache.doris.nereids.trees.plans.logical.LogicalTVFRelation;
 import org.apache.doris.nereids.trees.plans.logical.UsingJoin;
+import org.apache.doris.nereids.util.TypeCoercionUtils;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.base.Preconditions;
@@ -611,7 +613,7 @@ public class BindExpression implements AnalysisRuleFactory {
 
     @SuppressWarnings("unchecked")
     private <E extends Expression> E bindFunction(E expr, CascadesContext 
cascadesContext) {
-        return (E) FunctionBinder.INSTANCE.bind(expr, cascadesContext);
+        return (E) FunctionBinder.INSTANCE.rewrite(expr, new 
ExpressionRewriteContext(cascadesContext));
     }
 
     /**
@@ -671,14 +673,10 @@ public class BindExpression implements 
AnalysisRuleFactory {
         if (!(function instanceof TableGeneratingFunction)) {
             throw new AnalysisException(function.toSql() + " is not a 
TableGeneratingFunction");
         }
-        function = (BoundFunction) TypeCoercion.INSTANCE.rewrite(function, 
null);
+        function = (BoundFunction) 
TypeCoercionUtils.processBoundFunction(function);
         return function;
     }
 
-    public boolean canBind(Plan plan) {
-        return !plan.hasUnboundExpression() || plan.canBind();
-    }
-
     private void checkIfOutputAliasNameDuplicatedForGroupBy(List<Expression> 
expressions,
             List<NamedExpression> output) {
         // if group_by_and_having_use_alias_first=true, we should fall back to 
original planner until we
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ResolveOrdinalInOrderByAndGroupBy.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ResolveOrdinalInOrderByAndGroupBy.java
index 9a3a2d675e..7e6cecd6f3 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ResolveOrdinalInOrderByAndGroupBy.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ResolveOrdinalInOrderByAndGroupBy.java
@@ -20,8 +20,8 @@ package org.apache.doris.nereids.rules.analysis;
 import org.apache.doris.nereids.properties.OrderKey;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.FoldConstantRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.rules.FoldConstantRule;
 import org.apache.doris.nereids.trees.expressions.Alias;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.NamedExpression;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/AbstractExpressionRewriteRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/AbstractExpressionRewriteRule.java
similarity index 95%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/AbstractExpressionRewriteRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/AbstractExpressionRewriteRule.java
index eb3ef44e7a..852abfc176 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/AbstractExpressionRewriteRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/AbstractExpressionRewriteRule.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
 import org.apache.doris.nereids.trees.expressions.Expression;
 import 
org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionNormalization.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java
similarity index 59%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionNormalization.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java
index 7810173152..3cfd84a00c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionNormalization.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java
@@ -15,21 +15,20 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.BetweenToCompoundRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.CharacterLiteralTypeCoercion;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.DigitalMaskingConvert;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.FoldConstantRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.InPredicateDedup;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.InPredicateToEqualToRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeBinaryPredicatesRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyArithmeticComparisonRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyArithmeticRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyCastRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyNotExprRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SupportJavaDateFormatter;
-import org.apache.doris.nereids.rules.expression.rewrite.rules.TypeCoercion;
+import org.apache.doris.nereids.rules.expression.check.CheckCast;
+import org.apache.doris.nereids.rules.expression.rules.BetweenToCompoundRule;
+import org.apache.doris.nereids.rules.expression.rules.DigitalMaskingConvert;
+import org.apache.doris.nereids.rules.expression.rules.FoldConstantRule;
+import org.apache.doris.nereids.rules.expression.rules.InPredicateDedup;
+import 
org.apache.doris.nereids.rules.expression.rules.InPredicateToEqualToRule;
+import 
org.apache.doris.nereids.rules.expression.rules.NormalizeBinaryPredicatesRule;
+import 
org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticComparisonRule;
+import org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticRule;
+import org.apache.doris.nereids.rules.expression.rules.SimplifyCastRule;
+import org.apache.doris.nereids.rules.expression.rules.SimplifyNotExprRule;
+import 
org.apache.doris.nereids.rules.expression.rules.SupportJavaDateFormatter;
 import org.apache.doris.nereids.trees.expressions.Expression;
 
 import com.google.common.collect.ImmutableList;
@@ -49,15 +48,13 @@ public class ExpressionNormalization extends 
ExpressionRewrite {
             InPredicateDedup.INSTANCE,
             InPredicateToEqualToRule.INSTANCE,
             SimplifyNotExprRule.INSTANCE,
-            // TODO(morrySnow): remove type coercion from here after we could 
process subquery type coercion when bind
-            CharacterLiteralTypeCoercion.INSTANCE,
             SimplifyArithmeticRule.INSTANCE,
-            TypeCoercion.INSTANCE,
             FoldConstantRule.INSTANCE,
             SimplifyCastRule.INSTANCE,
             DigitalMaskingConvert.INSTANCE,
             SimplifyArithmeticComparisonRule.INSTANCE,
-            SupportJavaDateFormatter.INSTANCE
+            SupportJavaDateFormatter.INSTANCE,
+            CheckCast.INSTANCE
     );
 
     public ExpressionNormalization() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOptimization.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionOptimization.java
similarity index 78%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOptimization.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionOptimization.java
index 9e3eace63f..47840f226e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOptimization.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionOptimization.java
@@ -15,12 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.DistinctPredicatesRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.ExtractCommonFactorRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyComparisonPredicate;
-import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyRange;
+import org.apache.doris.nereids.rules.expression.rules.DistinctPredicatesRule;
+import org.apache.doris.nereids.rules.expression.rules.ExtractCommonFactorRule;
+import 
org.apache.doris.nereids.rules.expression.rules.SimplifyComparisonPredicate;
+import org.apache.doris.nereids.rules.expression.rules.SimplifyRange;
 
 import com.google.common.collect.ImmutableList;
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewrite.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRewrite.java
similarity index 99%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewrite.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRewrite.java
index 114e244c3a..3dc61bcbc7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewrite.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRewrite.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
 import org.apache.doris.nereids.properties.OrderKey;
 import org.apache.doris.nereids.rules.Rule;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteContext.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteContext.java
similarity index 82%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteContext.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteContext.java
index 37e571a0e3..2c1963060b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteContext.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteContext.java
@@ -15,18 +15,17 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
 import org.apache.doris.nereids.CascadesContext;
-import org.apache.doris.qe.ConnectContext;
 
 /**
  * expression rewrite context.
  */
 public class ExpressionRewriteContext {
-    public final ConnectContext connectContext;
+    public final CascadesContext cascadesContext;
 
     public ExpressionRewriteContext(CascadesContext cascadesContext) {
-        this.connectContext = cascadesContext.getConnectContext();
+        this.cascadesContext = cascadesContext;
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteRule.java
similarity index 94%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteRule.java
index c9ec2f92f9..1672d8c480 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteRule.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
 import org.apache.doris.nereids.trees.expressions.Expression;
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRuleExecutor.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleExecutor.java
similarity index 93%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRuleExecutor.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleExecutor.java
index 4058a566d0..ac7e6dae6b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRuleExecutor.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleExecutor.java
@@ -15,9 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeBinaryPredicatesRule;
+import 
org.apache.doris.nereids.rules.expression.rules.NormalizeBinaryPredicatesRule;
 import org.apache.doris.nereids.trees.expressions.Expression;
 
 import com.google.common.collect.ImmutableList;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java
new file mode 100644
index 0000000000..cc64baeb34
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java
@@ -0,0 +1,89 @@
+// 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.doris.nereids.rules.expression.check;
+
+import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
+import org.apache.doris.nereids.trees.expressions.Cast;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.types.ArrayType;
+import org.apache.doris.nereids.types.DataType;
+
+/**
+ * check cast valid
+ */
+public class CheckCast extends AbstractExpressionRewriteRule {
+
+    public static final CheckCast INSTANCE = new CheckCast();
+
+    @Override
+    public Expression visitCast(Cast cast, ExpressionRewriteContext context) {
+        rewrite(cast.child(), context);
+        DataType originalType = cast.child().getDataType();
+        DataType targetType = cast.getDataType();
+        if (!check(originalType, targetType)) {
+            throw new AnalysisException("cannot cast " + originalType + " to " 
+ targetType);
+        }
+        return cast;
+    }
+
+    private boolean check(DataType originalType, DataType targetType) {
+        if (originalType.isArrayType() && targetType.isArrayType()) {
+            return check(((ArrayType) originalType).getItemType(), 
((ArrayType) targetType).getItemType());
+        } else if (originalType.isMapType()) {
+            // TODO support map cast check when we support map
+            return false;
+        } else if (originalType.isStructType()) {
+            // TODO support struct cast check when we support struct
+            return false;
+        } else {
+            return checkPrimitiveType(originalType, targetType);
+        }
+    }
+
+    /**
+     * forbid this original and target type
+     *   1. boolean to date, datev2, datetime, datetimev2
+     *   2. original type is object type
+     *   3. target type is object type
+     *   4. original type is same with target type
+     *   5. target type is null type
+     */
+    private boolean checkPrimitiveType(DataType originalType, DataType 
targetType) {
+        if (!originalType.isPrimitive() || !targetType.isPrimitive()) {
+            return false;
+        }
+        if (originalType.equals(targetType)) {
+            return false;
+        }
+        if (originalType.isBooleanType() && targetType.isDateLikeType()) {
+            return false;
+        }
+        if (originalType.isNullType()) {
+            return true;
+        }
+        if (originalType.isObjectType() || targetType.isObjectType()) {
+            return false;
+        }
+        if (targetType.isNullType()) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/CharacterLiteralTypeCoercion.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/CharacterLiteralTypeCoercion.java
deleted file mode 100644
index 72a6b2976d..0000000000
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/CharacterLiteralTypeCoercion.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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.doris.nereids.rules.expression.rewrite.rules;
-
-import org.apache.doris.nereids.annotation.DependsRules;
-import org.apache.doris.nereids.jobs.batch.CheckLegalityBeforeTypeCoercion;
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
-import org.apache.doris.nereids.trees.expressions.BinaryArithmetic;
-import org.apache.doris.nereids.trees.expressions.Expression;
-import org.apache.doris.nereids.util.TypeCoercionUtils;
-
-/**
- * coercion character literal to another side
- */
-@Deprecated
-@DependsRules(CheckLegalityBeforeTypeCoercion.class)
-public class CharacterLiteralTypeCoercion extends 
AbstractExpressionRewriteRule {
-
-    public static final CharacterLiteralTypeCoercion INSTANCE = new 
CharacterLiteralTypeCoercion();
-
-    @Override
-    public Expression visitBinaryArithmetic(BinaryArithmetic binaryOperator, 
ExpressionRewriteContext context) {
-        Expression left = rewrite(binaryOperator.left(), context);
-        Expression right = rewrite(binaryOperator.right(), context);
-        return 
TypeCoercionUtils.processCharacterLiteralInBinaryOperator(binaryOperator, left, 
right);
-    }
-}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TypeCoercion.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TypeCoercion.java
deleted file mode 100644
index 29eaaaf0d5..0000000000
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TypeCoercion.java
+++ /dev/null
@@ -1,164 +0,0 @@
-// 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.doris.nereids.rules.expression.rewrite.rules;
-
-import org.apache.doris.catalog.PrimitiveType;
-import org.apache.doris.nereids.annotation.DependsRules;
-import org.apache.doris.nereids.exceptions.AnalysisException;
-import org.apache.doris.nereids.jobs.batch.CheckLegalityBeforeTypeCoercion;
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
-import org.apache.doris.nereids.trees.expressions.Between;
-import org.apache.doris.nereids.trees.expressions.BinaryArithmetic;
-import org.apache.doris.nereids.trees.expressions.BitNot;
-import org.apache.doris.nereids.trees.expressions.CaseWhen;
-import org.apache.doris.nereids.trees.expressions.Cast;
-import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
-import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
-import org.apache.doris.nereids.trees.expressions.Divide;
-import org.apache.doris.nereids.trees.expressions.Expression;
-import org.apache.doris.nereids.trees.expressions.InPredicate;
-import org.apache.doris.nereids.trees.expressions.IntegralDivide;
-import org.apache.doris.nereids.trees.expressions.Not;
-import org.apache.doris.nereids.trees.expressions.TimestampArithmetic;
-import 
org.apache.doris.nereids.trees.expressions.typecoercion.ImplicitCastInputTypes;
-import org.apache.doris.nereids.types.BigIntType;
-import org.apache.doris.nereids.types.coercion.AbstractDataType;
-import org.apache.doris.nereids.util.TypeCoercionUtils;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * a rule to add implicit cast for expressions.
- * This class is inspired by spark's TypeCoercion.
- * only process expressions generated by unnest subquery. other expressions 
already process by FunctionBinder.
- */
-@Deprecated
-@DependsRules(CheckLegalityBeforeTypeCoercion.class)
-public class TypeCoercion extends AbstractExpressionRewriteRule {
-
-    public static final TypeCoercion INSTANCE = new TypeCoercion();
-
-    @Override
-    public Expression visit(Expression expr, ExpressionRewriteContext ctx) {
-        if (expr instanceof ImplicitCastInputTypes) {
-            List<AbstractDataType> expectedInputTypes = 
((ImplicitCastInputTypes) expr).expectedInputTypes();
-            if (!expectedInputTypes.isEmpty()) {
-                return visitImplicitCastInputTypes(expr, expectedInputTypes, 
ctx);
-            }
-        }
-
-        return super.visit(expr, ctx);
-    }
-
-    @Override
-    public Expression visitBitNot(BitNot bitNot, ExpressionRewriteContext 
context) {
-        Expression child = rewrite(bitNot.child(), context);
-        if 
(child.getDataType().toCatalogDataType().getPrimitiveType().ordinal()
-                > PrimitiveType.LARGEINT.ordinal()) {
-            child = new Cast(child, BigIntType.INSTANCE);
-        }
-        return bitNot.withChildren(child);
-    }
-
-    @Override
-    public Expression visitDivide(Divide divide, ExpressionRewriteContext 
context) {
-        Expression left = rewrite(divide.left(), context);
-        Expression right = rewrite(divide.right(), context);
-        return divide.withChildren(left, right);
-    }
-
-    @Override
-    public Expression visitIntegralDivide(IntegralDivide integralDivide, 
ExpressionRewriteContext context) {
-        Expression left = rewrite(integralDivide.left(), context);
-        Expression right = rewrite(integralDivide.right(), context);
-        return integralDivide.withChildren(left, right);
-    }
-
-    @Override
-    public Expression visitBinaryArithmetic(BinaryArithmetic binaryArithmetic, 
ExpressionRewriteContext context) {
-        Expression left = rewrite(binaryArithmetic.left(), context);
-        Expression right = rewrite(binaryArithmetic.right(), context);
-        return binaryArithmetic.withChildren(left, right);
-    }
-
-    @Override
-    public Expression visitNot(Not not, ExpressionRewriteContext context) {
-        Expression child = rewrite(not.child(), context);
-        if (!child.getDataType().isBooleanType() && 
!child.getDataType().isNullType()) {
-            throw new AnalysisException(String.format(
-                    "Operand '%s' part of predicate " + "'%s' should return 
type 'BOOLEAN' but "
-                            + "returns type '%s'.",
-                    child.toSql(), not.toSql(), child.getDataType()));
-        }
-        return not.withChildren(child);
-    }
-
-    @Override
-    public Expression visitCompoundPredicate(CompoundPredicate 
compoundPredicate, ExpressionRewriteContext context) {
-        Expression left = rewrite(compoundPredicate.left(), context);
-        Expression right = rewrite(compoundPredicate.right(), context);
-        CompoundPredicate ret = (CompoundPredicate) 
compoundPredicate.withChildren(left, right);
-        return TypeCoercionUtils.processCompoundPredicate(ret);
-    }
-
-    @Override
-    public Expression visitComparisonPredicate(ComparisonPredicate cp, 
ExpressionRewriteContext context) {
-        Expression left = rewrite(cp.left(), context);
-        Expression right = rewrite(cp.right(), context);
-        return TypeCoercionUtils.processComparisonPredicate(cp, left, right);
-    }
-
-    @Override
-    public Expression visitCaseWhen(CaseWhen caseWhen, 
ExpressionRewriteContext context) {
-        List<Expression> rewrittenChildren = caseWhen.children().stream()
-                .map(e -> rewrite(e, context)).collect(Collectors.toList());
-        return caseWhen.withChildren(rewrittenChildren);
-    }
-
-    @Override
-    public Expression visitInPredicate(InPredicate inPredicate, 
ExpressionRewriteContext context) {
-        List<Expression> rewrittenChildren = inPredicate.children().stream()
-                .map(e -> rewrite(e, context)).collect(Collectors.toList());
-        return inPredicate.withChildren(rewrittenChildren);
-    }
-
-    @Override
-    public Expression visitTimestampArithmetic(TimestampArithmetic arithmetic, 
ExpressionRewriteContext context) {
-        Expression left = rewrite(arithmetic.left(), context);
-        Expression right = rewrite(arithmetic.right(), context);
-        return arithmetic.withChildren(left, right);
-    }
-
-    @Override
-    public Expression visitBetween(Between between, ExpressionRewriteContext 
context) {
-        List<Expression> rewrittenChildren = between.children().stream()
-                .map(e -> rewrite(e, context)).collect(Collectors.toList());
-        return between.withChildren(rewrittenChildren);
-    }
-
-    /**
-     * Do implicit cast for expression's children.
-     */
-    private Expression visitImplicitCastInputTypes(Expression expr,
-            List<AbstractDataType> expectedInputTypes, 
ExpressionRewriteContext ctx) {
-        expr = expr.withChildren(child -> rewrite(child, ctx));
-        return TypeCoercionUtils.implicitCastInputTypes(expr, 
expectedInputTypes);
-    }
-}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/BetweenToCompoundRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/BetweenToCompoundRule.java
similarity index 74%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/BetweenToCompoundRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/BetweenToCompoundRule.java
index 0ed915d2e7..17092ff7e6 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/BetweenToCompoundRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/BetweenToCompoundRule.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.And;
 import org.apache.doris.nereids.trees.expressions.Between;
 import org.apache.doris.nereids.trees.expressions.Expression;
@@ -37,8 +37,11 @@ public class BetweenToCompoundRule extends 
AbstractExpressionRewriteRule {
 
     @Override
     public Expression visitBetween(Between expr, ExpressionRewriteContext 
context) {
-        Expression left = new GreaterThanEqual(expr.getCompareExpr(), 
expr.getLowerBound());
-        Expression right = new LessThanEqual(expr.getCompareExpr(), 
expr.getUpperBound());
+        Expression compare = rewrite(expr.getCompareExpr(), context);
+        Expression lowerBound = rewrite(expr.getLowerBound(), context);
+        Expression upperBound = rewrite(expr.getUpperBound(), context);
+        Expression left = new GreaterThanEqual(compare, lowerBound);
+        Expression right = new LessThanEqual(compare, upperBound);
         return new And(left, right);
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ColumnBound.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnBound.java
similarity index 98%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ColumnBound.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnBound.java
index 562902dd0e..1012708bc3 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ColumnBound.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnBound.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.catalog.PartitionKey;
 import org.apache.doris.nereids.trees.expressions.literal.Literal;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ColumnRange.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnRange.java
similarity index 98%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ColumnRange.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnRange.java
index debd70ccb8..3fcce02cde 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ColumnRange.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnRange.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.nereids.trees.expressions.literal.Literal;
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/DigitalMaskingConvert.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DigitalMaskingConvert.java
similarity index 88%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/DigitalMaskingConvert.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DigitalMaskingConvert.java
index e297c2f120..5e38c0390b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/DigitalMaskingConvert.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DigitalMaskingConvert.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Concat;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.DigitalMasking;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/DistinctPredicatesRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DistinctPredicatesRule.java
similarity index 89%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/DistinctPredicatesRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DistinctPredicatesRule.java
index 24a8b06d00..8f21f7d348 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/DistinctPredicatesRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DistinctPredicatesRule.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.util.ExpressionUtils;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ExtractCommonFactorRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ExtractCommonFactorRule.java
similarity index 93%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ExtractCommonFactorRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ExtractCommonFactorRule.java
index d02a0da2d6..dd457e01d8 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ExtractCommonFactorRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ExtractCommonFactorRule.java
@@ -15,11 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.nereids.annotation.Developing;
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.util.ExpressionUtils;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRule.java
similarity index 75%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRule.java
index 9ec497c576..10b1e39da3 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRule.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Expression;
 
 /**
@@ -30,7 +30,9 @@ public class FoldConstantRule extends 
AbstractExpressionRewriteRule {
 
     @Override
     public Expression rewrite(Expression expr, ExpressionRewriteContext ctx) {
-        if (ctx.connectContext != null && 
ctx.connectContext.getSessionVariable().isEnableFoldConstantByBe()) {
+        if (ctx.cascadesContext != null
+                && ctx.cascadesContext.getConnectContext() != null
+                && 
ctx.cascadesContext.getConnectContext().getSessionVariable().isEnableFoldConstantByBe())
 {
             return new FoldConstantRuleOnBE().rewrite(expr, ctx);
         }
         return FoldConstantRuleOnFE.INSTANCE.rewrite(expr, ctx);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnBE.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java
similarity index 97%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnBE.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java
index da64459e7f..1e14685128 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnBE.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.analysis.Expr;
 import org.apache.doris.analysis.ExprId;
@@ -28,8 +28,8 @@ import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.TimeUtils;
 import org.apache.doris.common.util.VectorizedUtil;
 import org.apache.doris.nereids.glue.translator.ExpressionTranslator;
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Alias;
 import org.apache.doris.nereids.trees.expressions.Between;
 import org.apache.doris.nereids.trees.expressions.Cast;
@@ -91,7 +91,7 @@ public class FoldConstantRuleOnBE extends 
AbstractExpressionRewriteRule {
         }
         Map<String, Map<String, TExpr>> paramMap = new HashMap<>();
         paramMap.put("0", staleConstTExprMap);
-        Map<String, Expression> resultMap = evalOnBE(paramMap, constMap, 
context.connectContext);
+        Map<String, Expression> resultMap = evalOnBE(paramMap, constMap, 
context.cascadesContext.getConnectContext());
         if (!resultMap.isEmpty()) {
             return replace(root, constMap, resultMap);
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnFE.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java
similarity index 96%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnFE.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java
index 0bcdc86f7d..b48874790c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnFE.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java
@@ -15,11 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.cluster.ClusterNamespace;
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.AggregateExpression;
 import org.apache.doris.nereids.trees.expressions.And;
 import org.apache.doris.nereids.trees.expressions.BinaryArithmetic;
@@ -183,31 +183,31 @@ public class FoldConstantRuleOnFE extends 
AbstractExpressionRewriteRule {
 
     @Override
     public Expression visitDatabase(Database database, 
ExpressionRewriteContext context) {
-        String res = 
ClusterNamespace.getNameFromFullName(context.connectContext.getDatabase());
+        String res = 
ClusterNamespace.getNameFromFullName(context.cascadesContext.getConnectContext().getDatabase());
         return new VarcharLiteral(res);
     }
 
     @Override
     public Expression visitCurrentUser(CurrentUser currentUser, 
ExpressionRewriteContext context) {
-        String res = 
context.connectContext.get().getCurrentUserIdentity().toString();
+        String res = 
context.cascadesContext.getConnectContext().getCurrentUserIdentity().toString();
         return new VarcharLiteral(res);
     }
 
     @Override
     public Expression visitCurrentCatalog(CurrentCatalog currentCatalog, 
ExpressionRewriteContext context) {
-        String res = context.connectContext.get().getDefaultCatalog();
+        String res = 
context.cascadesContext.getConnectContext().getDefaultCatalog();
         return new VarcharLiteral(res);
     }
 
     @Override
     public Expression visitUser(User user, ExpressionRewriteContext context) {
-        String res = context.connectContext.get().getUserIdentity().toString();
+        String res = 
context.cascadesContext.getConnectContext().getUserIdentity().toString();
         return new VarcharLiteral(res);
     }
 
     @Override
     public Expression visitConnectionId(ConnectionId connectionId, 
ExpressionRewriteContext context) {
-        return new 
BigIntLiteral(context.connectContext.get().getConnectionId());
+        return new 
BigIntLiteral(context.cascadesContext.getConnectContext().getConnectionId());
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/FunctionBinder.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FunctionBinder.java
similarity index 88%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/FunctionBinder.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FunctionBinder.java
index 6e8a98d244..a3c4a2ee52 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/FunctionBinder.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FunctionBinder.java
@@ -15,14 +15,16 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.analysis;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.analysis.ArithmeticExpr.Operator;
 import org.apache.doris.catalog.FunctionRegistry;
 import org.apache.doris.catalog.PrimitiveType;
-import org.apache.doris.nereids.CascadesContext;
 import org.apache.doris.nereids.analyzer.UnboundFunction;
 import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.rules.analysis.ArithmeticFunctionBinder;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Between;
 import org.apache.doris.nereids.trees.expressions.BinaryArithmetic;
 import org.apache.doris.nereids.trees.expressions.BitNot;
@@ -42,7 +44,6 @@ import 
org.apache.doris.nereids.trees.expressions.TimestampArithmetic;
 import org.apache.doris.nereids.trees.expressions.functions.BoundFunction;
 import org.apache.doris.nereids.trees.expressions.functions.FunctionBuilder;
 import 
org.apache.doris.nereids.trees.expressions.typecoercion.ImplicitCastInputTypes;
-import 
org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter;
 import org.apache.doris.nereids.types.BigIntType;
 import org.apache.doris.nereids.types.coercion.AbstractDataType;
 import org.apache.doris.nereids.util.TypeCoercionUtils;
@@ -56,15 +57,11 @@ import java.util.stream.Collectors;
 /**
  * function binder
  */
-public class FunctionBinder extends DefaultExpressionRewriter<CascadesContext> 
{
+public class FunctionBinder extends AbstractExpressionRewriteRule {
     public static final FunctionBinder INSTANCE = new FunctionBinder();
 
-    public <E extends Expression> E bind(E expression, CascadesContext 
context) {
-        return (E) expression.accept(this, context);
-    }
-
     @Override
-    public Expression visit(Expression expr, CascadesContext context) {
+    public Expression visit(Expression expr, ExpressionRewriteContext context) 
{
         expr = super.visit(expr, context);
         expr.checkLegalityBeforeTypeCoercion();
         // this cannot be removed, because some function already construct in 
parser.
@@ -82,12 +79,12 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
      * 
********************************************************************************************
 */
 
     @Override
-    public Expression visitUnboundFunction(UnboundFunction unboundFunction, 
CascadesContext context) {
+    public Expression visitUnboundFunction(UnboundFunction unboundFunction, 
ExpressionRewriteContext context) {
         unboundFunction = 
unboundFunction.withChildren(unboundFunction.children().stream()
                 .map(e -> e.accept(this, 
context)).collect(Collectors.toList()));
 
         // bind function
-        FunctionRegistry functionRegistry = 
context.getConnectContext().getEnv().getFunctionRegistry();
+        FunctionRegistry functionRegistry = 
context.cascadesContext.getConnectContext().getEnv().getFunctionRegistry();
         String functionName = unboundFunction.getName();
         List<Object> arguments = unboundFunction.isDistinct()
                 ? ImmutableList.builder()
@@ -114,7 +111,7 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
      * e.g. YEARS_ADD、YEARS_SUB、DAYS_ADD 、DAYS_SUB
      */
     @Override
-    public Expression visitTimestampArithmetic(TimestampArithmetic arithmetic, 
CascadesContext context) {
+    public Expression visitTimestampArithmetic(TimestampArithmetic arithmetic, 
ExpressionRewriteContext context) {
         Expression left = arithmetic.left().accept(this, context);
         Expression right = arithmetic.right().accept(this, context);
 
@@ -138,7 +135,7 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
      * 
********************************************************************************************
 */
 
     @Override
-    public Expression visitBitNot(BitNot bitNot, CascadesContext context) {
+    public Expression visitBitNot(BitNot bitNot, ExpressionRewriteContext 
context) {
         Expression child = bitNot.child().accept(this, context);
         // type coercion
         if 
(child.getDataType().toCatalogDataType().getPrimitiveType().ordinal() > 
PrimitiveType.LARGEINT.ordinal()) {
@@ -148,7 +145,7 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
     }
 
     @Override
-    public Expression visitDivide(Divide divide, CascadesContext context) {
+    public Expression visitDivide(Divide divide, ExpressionRewriteContext 
context) {
         Expression left = divide.left().accept(this, context);
         Expression right = divide.right().accept(this, context);
 
@@ -157,7 +154,7 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
     }
 
     @Override
-    public Expression visitIntegralDivide(IntegralDivide integralDivide, 
CascadesContext context) {
+    public Expression visitIntegralDivide(IntegralDivide integralDivide, 
ExpressionRewriteContext context) {
         Expression left = integralDivide.left().accept(this, context);
         Expression right = integralDivide.right().accept(this, context);
 
@@ -166,14 +163,14 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
     }
 
     @Override
-    public Expression visitBinaryArithmetic(BinaryArithmetic binaryArithmetic, 
CascadesContext context) {
+    public Expression visitBinaryArithmetic(BinaryArithmetic binaryArithmetic, 
ExpressionRewriteContext context) {
         Expression left = binaryArithmetic.left().accept(this, context);
         Expression right = binaryArithmetic.right().accept(this, context);
         return TypeCoercionUtils.processBinaryArithmetic(binaryArithmetic, 
left, right);
     }
 
     @Override
-    public Expression visitCompoundPredicate(CompoundPredicate 
compoundPredicate, CascadesContext context) {
+    public Expression visitCompoundPredicate(CompoundPredicate 
compoundPredicate, ExpressionRewriteContext context) {
         Expression left = compoundPredicate.left().accept(this, context);
         Expression right = compoundPredicate.right().accept(this, context);
         CompoundPredicate ret = (CompoundPredicate) 
compoundPredicate.withChildren(left, right);
@@ -181,7 +178,7 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
     }
 
     @Override
-    public Expression visitNot(Not not, CascadesContext context) {
+    public Expression visitNot(Not not, ExpressionRewriteContext context) {
         Expression child = not.child().accept(this, context);
         if (!child.getDataType().isBooleanType() && 
!child.getDataType().isNullType()) {
             throw new AnalysisException(String.format(
@@ -193,14 +190,14 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
     }
 
     @Override
-    public Expression visitComparisonPredicate(ComparisonPredicate cp, 
CascadesContext context) {
+    public Expression visitComparisonPredicate(ComparisonPredicate cp, 
ExpressionRewriteContext context) {
         Expression left = cp.left().accept(this, context);
         Expression right = cp.right().accept(this, context);
         return TypeCoercionUtils.processComparisonPredicate(cp, left, right);
     }
 
     @Override
-    public Expression visitCaseWhen(CaseWhen caseWhen, CascadesContext 
context) {
+    public Expression visitCaseWhen(CaseWhen caseWhen, 
ExpressionRewriteContext context) {
         List<Expression> rewrittenChildren = caseWhen.children().stream()
                 .map(e -> e.accept(this, 
context)).collect(Collectors.toList());
         CaseWhen newCaseWhen = caseWhen.withChildren(rewrittenChildren);
@@ -209,7 +206,7 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
     }
 
     @Override
-    public Expression visitInPredicate(InPredicate inPredicate, 
CascadesContext context) {
+    public Expression visitInPredicate(InPredicate inPredicate, 
ExpressionRewriteContext context) {
         List<Expression> rewrittenChildren = inPredicate.children().stream()
                 .map(e -> e.accept(this, 
context)).collect(Collectors.toList());
         InPredicate newInPredicate = 
inPredicate.withChildren(rewrittenChildren);
@@ -217,7 +214,7 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
     }
 
     @Override
-    public Expression visitBetween(Between between, CascadesContext context) {
+    public Expression visitBetween(Between between, ExpressionRewriteContext 
context) {
         List<Expression> rewrittenChildren = between.children().stream()
                 .map(e -> e.accept(this, 
context)).collect(Collectors.toList());
         Between newBetween = between.withChildren(rewrittenChildren);
@@ -225,7 +222,7 @@ public class FunctionBinder extends 
DefaultExpressionRewriter<CascadesContext> {
     }
 
     @Override
-    public Expression visitInSubquery(InSubquery inSubquery, CascadesContext 
context) {
+    public Expression visitInSubquery(InSubquery inSubquery, 
ExpressionRewriteContext context) {
         Expression newCompareExpr = inSubquery.getCompareExpr().accept(this, 
context);
         Expression newListQuery = inSubquery.getListQuery().accept(this, 
context);
         ComparisonPredicate newCpAfterUnNestingSubquery =
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/InPredicateDedup.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/InPredicateDedup.java
similarity index 89%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/InPredicateDedup.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/InPredicateDedup.java
index 277883bb28..32f8e46da7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/InPredicateDedup.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/InPredicateDedup.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.InPredicate;
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/InPredicateToEqualToRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/InPredicateToEqualToRule.java
similarity index 91%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/InPredicateToEqualToRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/InPredicateToEqualToRule.java
index a729165077..64e4c91659 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/InPredicateToEqualToRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/InPredicateToEqualToRule.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.EqualTo;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.InPredicate;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/NormalizeBinaryPredicatesRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/NormalizeBinaryPredicatesRule.java
similarity index 86%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/NormalizeBinaryPredicatesRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/NormalizeBinaryPredicatesRule.java
index f2d30cf69f..9b1c88b930 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/NormalizeBinaryPredicatesRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/NormalizeBinaryPredicatesRule.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
 import org.apache.doris.nereids.trees.expressions.Expression;
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/OneListPartitionEvaluator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneListPartitionEvaluator.java
similarity index 96%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/OneListPartitionEvaluator.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneListPartitionEvaluator.java
index 4890b505c6..fcdd9c2a45 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/OneListPartitionEvaluator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneListPartitionEvaluator.java
@@ -15,12 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.catalog.ListPartitionItem;
 import org.apache.doris.common.Pair;
 import org.apache.doris.nereids.CascadesContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.expressions.literal.Literal;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/OnePartitionEvaluator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OnePartitionEvaluator.java
similarity index 97%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/OnePartitionEvaluator.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OnePartitionEvaluator.java
index bba8143b27..a2e5c332a7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/OnePartitionEvaluator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OnePartitionEvaluator.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/OneRangePartitionEvaluator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneRangePartitionEvaluator.java
similarity index 98%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/OneRangePartitionEvaluator.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneRangePartitionEvaluator.java
index 6f4337eacf..d03d3276ef 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/OneRangePartitionEvaluator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneRangePartitionEvaluator.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.analysis.LiteralExpr;
 import org.apache.doris.catalog.PartitionKey;
@@ -25,10 +25,10 @@ import org.apache.doris.catalog.Type;
 import org.apache.doris.common.Pair;
 import org.apache.doris.nereids.CascadesContext;
 import org.apache.doris.nereids.exceptions.AnalysisException;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.OneRangePartitionEvaluator.EvaluateRangeInput;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.OneRangePartitionEvaluator.EvaluateRangeResult;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.PartitionRangeExpander.PartitionSlotType;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
+import 
org.apache.doris.nereids.rules.expression.rules.OneRangePartitionEvaluator.EvaluateRangeInput;
+import 
org.apache.doris.nereids.rules.expression.rules.OneRangePartitionEvaluator.EvaluateRangeResult;
+import 
org.apache.doris.nereids.rules.expression.rules.PartitionRangeExpander.PartitionSlotType;
 import org.apache.doris.nereids.trees.expressions.And;
 import org.apache.doris.nereids.trees.expressions.EqualTo;
 import org.apache.doris.nereids.trees.expressions.Expression;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/PartitionPruner.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionPruner.java
similarity index 98%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/PartitionPruner.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionPruner.java
index 645559fdb4..7a53427f62 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/PartitionPruner.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionPruner.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.catalog.ListPartitionItem;
 import org.apache.doris.catalog.PartitionInfo;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/PartitionRangeExpander.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionRangeExpander.java
similarity index 99%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/PartitionRangeExpander.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionRangeExpander.java
index 413265c0eb..3441319b2b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/PartitionRangeExpander.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionRangeExpander.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.trees.expressions.Expression;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/PartitionSlotInput.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionSlotInput.java
similarity index 99%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/PartitionSlotInput.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionSlotInput.java
index d7f527f44f..44aaeade53 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/PartitionSlotInput.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionSlotInput.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyArithmeticComparisonRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticComparisonRule.java
similarity index 88%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyArithmeticComparisonRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticComparisonRule.java
index 16aee8d2ad..c5ab5119ce 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyArithmeticComparisonRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticComparisonRule.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Add;
 import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
 import org.apache.doris.nereids.trees.expressions.EqualTo;
@@ -29,10 +29,9 @@ import org.apache.doris.nereids.trees.expressions.LessThan;
 import org.apache.doris.nereids.trees.expressions.LessThanEqual;
 import org.apache.doris.nereids.trees.expressions.Multiply;
 import org.apache.doris.nereids.trees.expressions.Subtract;
+import org.apache.doris.nereids.util.TypeCoercionUtils;
 import org.apache.doris.nereids.util.TypeUtils;
 
-import com.google.common.collect.ImmutableList;
-
 /**
  * Simplify arithmetic comparison rule.
  * a + 1 > 1 => a > 0
@@ -73,7 +72,11 @@ public class SimplifyArithmeticComparisonRule extends 
AbstractExpressionRewriteR
                 }
             }
         }
-        return predicate.withChildren(ImmutableList.of(left, right));
+        if (left != predicate.left() || right != predicate.right()) {
+            return TypeCoercionUtils.processComparisonPredicate(predicate, 
left, right);
+        } else {
+            return predicate;
+        }
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyArithmeticRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticRule.java
similarity index 97%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyArithmeticRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticRule.java
index d85d53fadc..6ee7d2646f 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyArithmeticRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticRule.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Add;
 import org.apache.doris.nereids.trees.expressions.BinaryArithmetic;
 import org.apache.doris.nereids.trees.expressions.Divide;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyCastRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyCastRule.java
similarity index 95%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyCastRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyCastRule.java
index d777a2f8b7..dad18d8aaf 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyCastRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyCastRule.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Cast;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
@@ -65,7 +65,6 @@ public class SimplifyCastRule extends 
AbstractExpressionRewriteRule {
         }
 
         if (child instanceof Literal) {
-            // TODO: process other type
             DataType castType = cast.getDataType();
             if (castType instanceof StringType) {
                 if (child instanceof VarcharLiteral) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyComparisonPredicate.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java
similarity index 96%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyComparisonPredicate.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java
index 5308e08fb9..1ab38d2ffe 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyComparisonPredicate.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java
@@ -15,11 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.nereids.exceptions.AnalysisException;
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Cast;
 import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
 import org.apache.doris.nereids.trees.expressions.EqualTo;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyNotExprRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyNotExprRule.java
similarity index 92%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyNotExprRule.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyNotExprRule.java
index 7954262ee7..7268d6e832 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyNotExprRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyNotExprRule.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
 import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
 import org.apache.doris.nereids.trees.expressions.Expression;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyRange.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java
similarity index 98%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyRange.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java
index da2904fb04..392207bf9a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyRange.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java
@@ -15,11 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRuleExecutor;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.ExpressionRuleExecutor;
 import org.apache.doris.nereids.trees.expressions.And;
 import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
 import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SupportJavaDateFormatter.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SupportJavaDateFormatter.java
similarity index 93%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SupportJavaDateFormatter.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SupportJavaDateFormatter.java
index 988ac2fafc..f861944078 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SupportJavaDateFormatter.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SupportJavaDateFormatter.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.DateFormat;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.FromUnixtime;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TryEliminateUninterestedPredicates.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/TryEliminateUninterestedPredicates.java
similarity index 95%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TryEliminateUninterestedPredicates.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/TryEliminateUninterestedPredicates.java
index d5ffa46db1..6db101a4ca 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TryEliminateUninterestedPredicates.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/TryEliminateUninterestedPredicates.java
@@ -15,11 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.nereids.CascadesContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.TryEliminateUninterestedPredicates.Context;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
+import 
org.apache.doris.nereids.rules.expression.rules.TryEliminateUninterestedPredicates.Context;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/UnknownPartitionEvaluator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/UnknownPartitionEvaluator.java
similarity index 96%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/UnknownPartitionEvaluator.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/UnknownPartitionEvaluator.java
index de74e526de..1325635eb7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/UnknownPartitionEvaluator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/UnknownPartitionEvaluator.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite.rules;
+package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.catalog.PartitionItem;
 import org.apache.doris.nereids.trees.expressions.Expression;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/AggregateStrategies.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/AggregateStrategies.java
index a65440379d..aa39ad3467 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/AggregateStrategies.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/AggregateStrategies.java
@@ -29,9 +29,7 @@ import org.apache.doris.nereids.properties.PhysicalProperties;
 import org.apache.doris.nereids.properties.RequireProperties;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.FoldConstantRuleOnFE;
-import org.apache.doris.nereids.rules.expression.rewrite.rules.TypeCoercion;
+import org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnFE;
 import org.apache.doris.nereids.rules.rewrite.logical.NormalizeAggregate;
 import org.apache.doris.nereids.trees.expressions.AggregateExpression;
 import org.apache.doris.nereids.trees.expressions.Alias;
@@ -63,6 +61,7 @@ import 
org.apache.doris.nereids.trees.plans.physical.PhysicalOlapScan;
 import 
org.apache.doris.nereids.trees.plans.physical.PhysicalStorageLayerAggregate;
 import 
org.apache.doris.nereids.trees.plans.physical.PhysicalStorageLayerAggregate.PushDownAggOp;
 import org.apache.doris.nereids.util.ExpressionUtils;
+import org.apache.doris.nereids.util.TypeCoercionUtils;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.statistics.Statistics;
 
@@ -1254,8 +1253,7 @@ public class AggregateStrategies implements 
ImplementationRuleFactory {
 
     // don't invoke the ExpressionNormalization, because the expression maybe 
simplified and get rid of some slots
     private If assignNullType(If ifExpr, CascadesContext cascadesContext) {
-        ExpressionRewriteContext context = new 
ExpressionRewriteContext(cascadesContext);
-        If ifWithCoercion = (If) TypeCoercion.INSTANCE.rewrite(ifExpr, 
context);
+        If ifWithCoercion = (If) 
TypeCoercionUtils.processBoundFunction(ifExpr);
         Expression trueValue = ifWithCoercion.getArgument(1);
         if (trueValue instanceof Cast && trueValue.child(0) instanceof 
NullLiteral) {
             List<Expression> newArgs = 
Lists.newArrayList(ifWithCoercion.getArguments());
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/EliminateGroupByConstant.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/EliminateGroupByConstant.java
index 7598352e1e..a9f3650cb4 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/EliminateGroupByConstant.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/EliminateGroupByConstant.java
@@ -19,8 +19,8 @@ package org.apache.doris.nereids.rules.rewrite.logical;
 
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.FoldConstantRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.rules.FoldConstantRule;
 import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.NamedExpression;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneOlapScanPartition.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneOlapScanPartition.java
index c9e07e9372..96c7dc94c2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneOlapScanPartition.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneOlapScanPartition.java
@@ -21,7 +21,7 @@ import org.apache.doris.catalog.OlapTable;
 import org.apache.doris.catalog.PartitionInfo;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
-import org.apache.doris.nereids.rules.expression.rewrite.rules.PartitionPruner;
+import org.apache.doris.nereids.rules.expression.rules.PartitionPruner;
 import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Divide.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Divide.java
index 8180fb9eac..e49ecf151e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Divide.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Divide.java
@@ -67,10 +67,10 @@ public class Divide extends BinaryArithmetic implements 
AlwaysNullable {
             retPercision = DecimalV3Type.MAX_DECIMAL128_PRECISION;
         }
         int targetScale = t1.getScale() + t2.getScale();
-        Preconditions.checkState(retPercision > targetScale,
+        Preconditions.checkState(retPercision >= targetScale,
                 "target scale " + targetScale + " larger than precision " + 
retPercision
                 + " in Divide return type");
-        Preconditions.checkState(retPercision > retScale,
+        Preconditions.checkState(retPercision >= retScale,
                 "scale " + retScale + " larger than precision " + retPercision
                         + " in Divide return type");
         return DecimalV3Type.createDecimalV3Type(retPercision, retScale);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Multiply.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Multiply.java
index 33dc97cdcc..bb83db1c72 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Multiply.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Multiply.java
@@ -49,7 +49,7 @@ public class Multiply extends BinaryArithmetic implements 
CheckOverflowNullable
         if (retPercision > DecimalV3Type.MAX_DECIMAL128_PRECISION) {
             retPercision = DecimalV3Type.MAX_DECIMAL128_PRECISION;
         }
-        Preconditions.checkState(retPercision > retScale,
+        Preconditions.checkState(retPercision >= retScale,
                 "scale " + retScale + " larger than precision " + retPercision
                         + " in Multiply return type");
         return DecimalV3Type.createDecimalV3Type(retPercision, retScale);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DigitalMasking.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DigitalMasking.java
index 5d20c3bbbd..19789fba08 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DigitalMasking.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DigitalMasking.java
@@ -23,7 +23,6 @@ import 
org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
 import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
 import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
-import org.apache.doris.nereids.types.BigIntType;
 import org.apache.doris.nereids.types.VarcharType;
 
 import com.google.common.base.Preconditions;
@@ -38,7 +37,7 @@ public class DigitalMasking extends ScalarFunction
         implements UnaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
-            
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(BigIntType.INSTANCE)
+            
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(VarcharType.SYSTEM_DEFAULT)
     );
 
     /**
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
index ef4f26c5e0..2c9cf77878 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
@@ -46,7 +46,7 @@ import java.util.Objects;
  */
 public abstract class Literal extends Expression implements LeafExpression, 
Comparable<Literal> {
 
-    private final DataType dataType;
+    protected final DataType dataType;
 
     /**
      * Constructor for Literal.
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NullLiteral.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NullLiteral.java
index ba70800e81..6dd8492ba1 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NullLiteral.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NullLiteral.java
@@ -31,8 +31,6 @@ public class NullLiteral extends Literal {
 
     public static final NullLiteral INSTANCE = new NullLiteral();
 
-    private DataType dataType;
-
     public NullLiteral() {
         super(NullType.INSTANCE);
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
index 5e6706e9b0..7e296b55ae 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
@@ -491,12 +491,24 @@ public abstract class DataType implements 
AbstractDataType {
         return this instanceof HllType;
     }
 
+    public boolean isComplexType() {
+        return !isPrimitive();
+    }
+
     public boolean isArrayType() {
         return this instanceof ArrayType;
     }
 
+    public boolean isMapType() {
+        return this instanceof MapType;
+    }
+
+    public boolean isStructType() {
+        return this instanceof StructType;
+    }
+
     public boolean isOnlyMetricType() {
-        return isObjectType() || isArrayType();
+        return isObjectType() || isComplexType() || isJsonType();
     }
 
     public boolean isObjectType() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
index 25ba707624..e7b068dc11 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
@@ -18,8 +18,8 @@
 package org.apache.doris.nereids.util;
 
 import org.apache.doris.nereids.CascadesContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.FoldConstantRule;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.rules.FoldConstantRule;
 import org.apache.doris.nereids.trees.TreeNode;
 import org.apache.doris.nereids.trees.expressions.And;
 import org.apache.doris.nereids.trees.expressions.Cast;
@@ -356,7 +356,7 @@ public class ExpressionUtils {
                 Expression evalExpr = FoldConstantRule.INSTANCE.rewrite(
                         ExpressionUtils.replace(predicate, replaceMap),
                         new ExpressionRewriteContext(cascadesContext));
-                if (nullLiteral.equals(evalExpr) || 
BooleanLiteral.FALSE.equals(evalExpr)) {
+                if (evalExpr.isNullLiteral() || 
BooleanLiteral.FALSE.equals(evalExpr)) {
                     notNullSlots.add(slot);
                 }
             }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
index d499fe87f9..053dc6b1a7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
@@ -249,7 +249,7 @@ public class TypeCoercionUtils {
         return Type.canCastTo(input.toCatalogDataType(), 
target.toCatalogDataType());
     }
 
-    private static void checkCanCastTo(DataType input, DataType target) {
+    public static void checkCanCastTo(DataType input, DataType target) {
         if (canCastTo(input, target)) {
             return;
         }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/CheckExpressionLegalityTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/CheckExpressionLegalityTest.java
index 4a8f642760..ce72d0d93d 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/CheckExpressionLegalityTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/CheckExpressionLegalityTest.java
@@ -20,7 +20,7 @@ package org.apache.doris.nereids.rules.analysis;
 import org.apache.doris.common.ExceptionChecker;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.jobs.batch.CheckLegalityAfterRewrite;
-import org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewrite;
+import org.apache.doris.nereids.rules.expression.ExpressionRewrite;
 import 
org.apache.doris.nereids.trees.expressions.functions.agg.BitmapUnionCount;
 import org.apache.doris.nereids.trees.expressions.functions.agg.Count;
 import org.apache.doris.nereids.util.MemoPatternMatchSupported;
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlotsTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlotsTest.java
index 51228c437f..4c1fec2ba5 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlotsTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlotsTest.java
@@ -21,8 +21,8 @@ import org.apache.doris.common.ExceptionChecker;
 import org.apache.doris.nereids.datasets.tpch.AnalyzeCheckTestBase;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.properties.OrderKey;
-import org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewrite;
-import org.apache.doris.nereids.rules.expression.rewrite.rules.TypeCoercion;
+import org.apache.doris.nereids.rules.expression.ExpressionRewrite;
+import org.apache.doris.nereids.rules.expression.rules.FunctionBinder;
 import org.apache.doris.nereids.trees.expressions.Add;
 import org.apache.doris.nereids.trees.expressions.Alias;
 import org.apache.doris.nereids.trees.expressions.Cast;
@@ -100,7 +100,7 @@ public class FillUpMissingSlotsTest extends 
AnalyzeCheckTestBase implements Memo
         );
         Alias value = new Alias(new ExprId(3), a1, "value");
         PlanChecker.from(connectContext).analyze(sql)
-                .applyBottomUp(new ExpressionRewrite(TypeCoercion.INSTANCE))
+                .applyBottomUp(new ExpressionRewrite(FunctionBinder.INSTANCE))
                 .matchesFromRoot(
                     logicalProject(
                         logicalFilter(
@@ -111,7 +111,7 @@ public class FillUpMissingSlotsTest extends 
AnalyzeCheckTestBase implements Memo
 
         sql = "SELECT a1 as value FROM t1 GROUP BY a1 HAVING value > 0";
         PlanChecker.from(connectContext).analyze(sql)
-                .applyBottomUp(new ExpressionRewrite(TypeCoercion.INSTANCE))
+                .applyBottomUp(new ExpressionRewrite(FunctionBinder.INSTANCE))
                 .matchesFromRoot(
                     logicalProject(
                         logicalFilter(
@@ -131,7 +131,7 @@ public class FillUpMissingSlotsTest extends 
AnalyzeCheckTestBase implements Memo
         );
         Alias sumA2 = new Alias(new ExprId(3), new Sum(a2), "SUM(a2)");
         PlanChecker.from(connectContext).analyze(sql)
-                .applyBottomUp(new ExpressionRewrite(TypeCoercion.INSTANCE))
+                .applyBottomUp(new ExpressionRewrite(FunctionBinder.INSTANCE))
                 .matchesFromRoot(
                     logicalProject(
                         logicalFilter(
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTest.java
similarity index 93%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTest.java
index 0b64b197b2..0dbaf6d30c 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTest.java
@@ -15,17 +15,17 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
-
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.BetweenToCompoundRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.DistinctPredicatesRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.ExtractCommonFactorRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.InPredicateDedup;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.InPredicateToEqualToRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeBinaryPredicatesRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyCastRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyComparisonPredicate;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyNotExprRule;
+package org.apache.doris.nereids.rules.expression;
+
+import org.apache.doris.nereids.rules.expression.rules.BetweenToCompoundRule;
+import org.apache.doris.nereids.rules.expression.rules.DistinctPredicatesRule;
+import org.apache.doris.nereids.rules.expression.rules.ExtractCommonFactorRule;
+import org.apache.doris.nereids.rules.expression.rules.InPredicateDedup;
+import 
org.apache.doris.nereids.rules.expression.rules.InPredicateToEqualToRule;
+import 
org.apache.doris.nereids.rules.expression.rules.NormalizeBinaryPredicatesRule;
+import org.apache.doris.nereids.rules.expression.rules.SimplifyCastRule;
+import 
org.apache.doris.nereids.rules.expression.rules.SimplifyComparisonPredicate;
+import org.apache.doris.nereids.rules.expression.rules.SimplifyNotExprRule;
 import org.apache.doris.nereids.trees.expressions.Cast;
 import org.apache.doris.nereids.trees.expressions.EqualTo;
 import org.apache.doris.nereids.trees.expressions.Expression;
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTestHelper.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTestHelper.java
similarity index 96%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTestHelper.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTestHelper.java
index 67315757d8..8ee43dbfd2 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTestHelper.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/ExpressionRewriteTestHelper.java
@@ -15,13 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
 import org.apache.doris.nereids.CascadesContext;
 import org.apache.doris.nereids.analyzer.UnboundRelation;
 import org.apache.doris.nereids.analyzer.UnboundSlot;
 import org.apache.doris.nereids.parser.NereidsParser;
-import org.apache.doris.nereids.rules.analysis.FunctionBinder;
+import org.apache.doris.nereids.rules.expression.rules.FunctionBinder;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.expressions.SlotReference;
@@ -104,7 +104,7 @@ public abstract class ExpressionRewriteTestHelper {
     }
 
     private Expression typeCoercion(Expression expression) {
-        return FunctionBinder.INSTANCE.bind(expression, null);
+        return FunctionBinder.INSTANCE.rewrite(expression, null);
     }
 
     private DataType getType(char t) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/FoldConstantTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java
similarity index 98%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/FoldConstantTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java
index 515370b1c9..5aac88873f 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/FoldConstantTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java
@@ -15,10 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
 import org.apache.doris.analysis.ArithmeticExpr.Operator;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.FoldConstantRuleOnFE;
+import org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnFE;
 import org.apache.doris.nereids.trees.expressions.Cast;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.GreaterThan;
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/SimplifyArithmeticRuleTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyArithmeticRuleTest.java
similarity index 92%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/SimplifyArithmeticRuleTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyArithmeticRuleTest.java
index 16d71d8f5d..8b9f48010a 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/SimplifyArithmeticRuleTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyArithmeticRuleTest.java
@@ -15,12 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.FoldConstantRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyArithmeticComparisonRule;
-import 
org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyArithmeticRule;
-import org.apache.doris.nereids.rules.expression.rewrite.rules.TypeCoercion;
+import org.apache.doris.nereids.rules.expression.rules.FoldConstantRule;
+import org.apache.doris.nereids.rules.expression.rules.FunctionBinder;
+import 
org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticComparisonRule;
+import org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticRule;
 
 import com.google.common.collect.ImmutableList;
 import org.junit.jupiter.api.Test;
@@ -30,7 +30,7 @@ public class SimplifyArithmeticRuleTest extends 
ExpressionRewriteTestHelper {
     public void testSimplifyArithmetic() {
         executor = new ExpressionRuleExecutor(ImmutableList.of(
                 SimplifyArithmeticRule.INSTANCE,
-                TypeCoercion.INSTANCE,
+                FunctionBinder.INSTANCE,
                 FoldConstantRule.INSTANCE
         ));
         assertRewriteAfterTypeCoercion("IA", "IA");
@@ -59,7 +59,7 @@ public class SimplifyArithmeticRuleTest extends 
ExpressionRewriteTestHelper {
                 FoldConstantRule.INSTANCE,
                 SimplifyArithmeticComparisonRule.INSTANCE,
                 SimplifyArithmeticRule.INSTANCE,
-                TypeCoercion.INSTANCE,
+                FunctionBinder.INSTANCE,
                 FoldConstantRule.INSTANCE
         ));
         assertRewriteAfterTypeCoercion("IA", "IA");
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/SimplifyRangeTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java
similarity index 98%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/SimplifyRangeTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java
index a4a62503b9..68aad77c64 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/SimplifyRangeTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java
@@ -15,13 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.expression.rewrite;
+package org.apache.doris.nereids.rules.expression;
 
 import org.apache.doris.nereids.CascadesContext;
 import org.apache.doris.nereids.analyzer.UnboundRelation;
 import org.apache.doris.nereids.analyzer.UnboundSlot;
 import org.apache.doris.nereids.parser.NereidsParser;
-import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyRange;
+import org.apache.doris.nereids.rules.expression.rules.SimplifyRange;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.expressions.SlotReference;
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/TypeCoercionTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/TypeCoercionTest.java
deleted file mode 100644
index 2260516a38..0000000000
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/TypeCoercionTest.java
+++ /dev/null
@@ -1,204 +0,0 @@
-// 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.doris.nereids.rules.expression.rewrite;
-
-import org.apache.doris.nereids.exceptions.AnalysisException;
-import org.apache.doris.nereids.rules.expression.rewrite.rules.TypeCoercion;
-import org.apache.doris.nereids.trees.expressions.Add;
-import org.apache.doris.nereids.trees.expressions.CaseWhen;
-import org.apache.doris.nereids.trees.expressions.Cast;
-import org.apache.doris.nereids.trees.expressions.Divide;
-import org.apache.doris.nereids.trees.expressions.Expression;
-import org.apache.doris.nereids.trees.expressions.InPredicate;
-import org.apache.doris.nereids.trees.expressions.LessThanEqual;
-import org.apache.doris.nereids.trees.expressions.WhenClause;
-import org.apache.doris.nereids.trees.expressions.functions.agg.Avg;
-import org.apache.doris.nereids.trees.expressions.functions.agg.Sum;
-import org.apache.doris.nereids.trees.expressions.functions.scalar.Substring;
-import org.apache.doris.nereids.trees.expressions.functions.scalar.Year;
-import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
-import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
-import org.apache.doris.nereids.trees.expressions.literal.DateLiteral;
-import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral;
-import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral;
-import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
-import org.apache.doris.nereids.trees.expressions.literal.Literal;
-import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral;
-import org.apache.doris.nereids.trees.expressions.literal.StringLiteral;
-import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
-import org.apache.doris.nereids.types.DataType;
-import org.apache.doris.nereids.types.DateV2Type;
-import org.apache.doris.nereids.types.DecimalV2Type;
-import org.apache.doris.nereids.types.DoubleType;
-import org.apache.doris.nereids.types.IntegerType;
-import org.apache.doris.nereids.types.TinyIntType;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-public class TypeCoercionTest extends ExpressionRewriteTestHelper {
-
-    @BeforeEach
-    public void setUp() {
-        executor = new 
ExpressionRuleExecutor(ImmutableList.of(TypeCoercion.INSTANCE));
-    }
-
-    @Test
-    public void testSubStringImplicitCast() {
-        Expression expression = new Substring(
-                new StringLiteral("abc"),
-                new StringLiteral("1"),
-                new StringLiteral("3")
-        );
-        Expression expected = new Substring(
-                new StringLiteral("abc"),
-                new Cast(new StringLiteral("1"), IntegerType.INSTANCE),
-                new Cast(new StringLiteral("3"), IntegerType.INSTANCE)
-        );
-        assertRewrite(expression, expected);
-    }
-
-    @Test
-    public void testLikeImplicitCast() {
-        String expression = "1 like 5";
-        String expected = "cast(1 as varchar) like cast(5 as varchar)";
-        assertRewrite(expression, expected);
-    }
-
-    @Test
-    public void testRegexImplicitCast() {
-        String expression = "1 regexp 5";
-        String expected = "cast(1 as varchar) regexp cast(5 as varchar)";
-        assertRewrite(expression, expected);
-    }
-
-    @Test
-    public void testYearImplicitCast() {
-        // date to datev2
-        Expression expression = new Year(new DateLiteral("2022-01-01"));
-        Expression expected = new Year(new Cast(new DateLiteral("2022-01-01"), 
DateV2Type.INSTANCE));
-        assertRewrite(expression, expected);
-    }
-
-    @Test
-    public void testSumImplicitCast() {
-        Assertions.assertThrows(AnalysisException.class, () -> {
-            checkAndGetDataType(new Sum(new StringLiteral("1")));
-        });
-    }
-
-    @Test
-    public void testAvgImplicitCast() {
-        Assertions.assertThrows(AnalysisException.class, () -> {
-            checkAndGetDataType(new Avg(new StringLiteral("1")));
-        });
-    }
-
-    @Test
-    public void testBinaryPredicate() {
-        Expression left = new DecimalLiteral(new BigDecimal(2.4));
-        Expression right = new TinyIntLiteral((byte) 2);
-        Expression lessThanEq = new LessThanEqual(left, right);
-        Expression rewrittenPred =
-                new LessThanEqual(
-                        left,
-                        new Cast(right, left.getDataType()));
-        assertRewrite(lessThanEq, rewrittenPred);
-
-        rewrittenPred =
-                new LessThanEqual(
-                        new Cast(right, left.getDataType()),
-                        left
-                        );
-        lessThanEq = new LessThanEqual(right, left);
-        assertRewrite(lessThanEq, rewrittenPred);
-
-        left = new DecimalLiteral(new BigDecimal(1));
-        lessThanEq = new LessThanEqual(left, right);
-        rewrittenPred =
-                new LessThanEqual(
-                        new Cast(left, 
DecimalV2Type.forType(TinyIntType.INSTANCE)),
-                        new Cast(right, 
DecimalV2Type.forType(TinyIntType.INSTANCE))
-                );
-        assertRewrite(lessThanEq, rewrittenPred);
-    }
-
-    @Test
-    public void testCaseWhenTypeCoercion() {
-        WhenClause actualWhenClause1 = new WhenClause(BooleanLiteral.TRUE, new 
SmallIntLiteral((short) 1));
-        WhenClause actualWhenClause2 = new WhenClause(BooleanLiteral.TRUE, new 
DoubleLiteral(1.5));
-        List<WhenClause> actualWhenClauses = 
Lists.newArrayList(actualWhenClause1, actualWhenClause2);
-        Expression actualDefaultValue = new IntegerLiteral(1);
-        Expression actual = new CaseWhen(actualWhenClauses, 
actualDefaultValue);
-
-        WhenClause expectedWhenClause1 = new WhenClause(BooleanLiteral.TRUE,
-                new Cast(new SmallIntLiteral((short) 1), DoubleType.INSTANCE));
-        WhenClause expectedWhenClause2 = new WhenClause(BooleanLiteral.TRUE,
-                new DoubleLiteral(1.5));
-        List<WhenClause> expectedWhenClauses = 
Lists.newArrayList(expectedWhenClause1, expectedWhenClause2);
-        Expression expectedDefaultValue = new Cast(new IntegerLiteral(1), 
DoubleType.INSTANCE);
-        Expression expected = new CaseWhen(expectedWhenClauses, 
expectedDefaultValue);
-
-        assertRewrite(actual, expected);
-    }
-
-    @Test
-    public void testInPredicate() {
-        Expression actualCompare = new DoubleLiteral(1.5);
-        Expression actualOption1 = new StringLiteral("hello");
-        Expression actualOption2 = new IntegerLiteral(1);
-        List<Expression> actualOptions = Lists.newArrayList(actualOption1, 
actualOption2);
-        Expression actual = new InPredicate(actualCompare, actualOptions);
-
-        Expression expectedCompare = new DoubleLiteral(1.5);
-        Expression expectedOption1 = new Cast(new StringLiteral("hello"), 
DoubleType.INSTANCE);
-        Expression expectedOption2 = new Cast(new IntegerLiteral(1), 
DoubleType.INSTANCE);
-        List<Expression> expectedOptions = Lists.newArrayList(expectedOption1, 
expectedOption2);
-        Expression expected = new InPredicate(expectedCompare, 
expectedOptions);
-
-        assertRewrite(actual, expected);
-    }
-
-    @Test
-    public void testBinaryOperator() {
-        Expression actual = new Divide(new SmallIntLiteral((short) 1), new 
BigIntLiteral(10L));
-        Expression expected = new Divide(new Cast(Literal.of((short) 1), 
DoubleType.INSTANCE),
-                new Cast(Literal.of(10L), DoubleType.INSTANCE));
-        assertRewrite(actual, expected);
-
-        Expression actual1 = new Add(new IntegerLiteral(1), new 
Add(BooleanLiteral.TRUE, new StringLiteral("2")));
-        Expression expected1 = new Add(new Cast(new IntegerLiteral(1), 
DoubleType.INSTANCE), new Add(
-                new Cast(BooleanLiteral.TRUE, DoubleType.INSTANCE),
-                new Cast(new StringLiteral("2"), DoubleType.INSTANCE)));
-        assertRewrite(actual1, expected1);
-
-        Expression actual2 = new Add(new IntegerLiteral(1), new 
Add(BooleanLiteral.TRUE, new StringLiteral("x")));
-        Assertions.assertThrows(IllegalStateException.class, () -> 
assertRewrite(actual2, null));
-    }
-
-    private DataType checkAndGetDataType(Expression expression) {
-        expression.checkLegalityBeforeTypeCoercion();
-        return expression.getDataType();
-    }
-}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org


Reply via email to