morrySnow commented on code in PR #12151:
URL: https://github.com/apache/doris/pull/12151#discussion_r977225255


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TypeCoercion.java:
##########
@@ -82,6 +85,23 @@ public Expression visitBinaryOperator(BinaryOperator 
binaryOperator, ExpressionR
                 .orElse(binaryOperator.withChildren(left, right));
     }
 
+    @Override
+    public Expression visitDivide(Divide divide, ExpressionRewriteContext 
context) {

Review Comment:
   pls remove TODO at L48



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java:
##########
@@ -945,6 +946,9 @@ private Expression withPredicate(Expression 
valueExpression, PredicateContext ct
                         );
                     }
                     break;
+                case DorisParser.NULL:

Review Comment:
   pls remove TODO at L388 in function `visitPredicated`



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java:
##########
@@ -257,4 +259,20 @@ public static List<Expression> mergeArguments(Object... 
arguments) {
         }
         return builder.build();
     }
+
+    public static boolean isAllLiteral(Expression... children) {
+        return Arrays.stream(children).allMatch(c -> c instanceof Literal);
+    }
+
+    public static boolean isAllLiteral(List<Expression> children) {
+        return children.stream().allMatch(c -> c instanceof Literal);
+    }
+
+    public static boolean hasNullLiteral(List<Expression> children) {
+        return children.stream().anyMatch(c -> c instanceof NullLiteral);
+    }
+
+    public static boolean allNullLiteral(List<Expression> children) {

Review Comment:
   ```suggestion
       public static boolean isAllNullLiteral(List<Expression> children) {
   ```



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionEvaluator.java:
##########
@@ -0,0 +1,210 @@
+// 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.trees.expressions;
+
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.AnalysisException;
+import 
org.apache.doris.nereids.trees.expressions.functions.ExecutableFunctions;
+import 
org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
+import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
+import org.apache.doris.nereids.types.DataType;
+import org.apache.doris.rewrite.FEFunction;
+import org.apache.doris.rewrite.FEFunctionList;
+
+import com.google.common.collect.ImmutableMultimap;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * An expression evaluator that evaluates the value of an expression.
+ */
+public enum ExpressionEvaluator {
+    INSTANCE;
+    private ImmutableMultimap<String, FunctionInvoker> functions;
+
+    ExpressionEvaluator() {
+        registerFunctions();
+    }
+
+    /**
+     * Evaluate the value of the expression.
+     */
+    public Expression eval(Expression expression) {
+
+        if (!expression.isConstant() || expression instanceof 
AggregateFunction) {
+            return expression;
+        }
+
+        String fnName = null;
+        DataType[] args = null;
+        if (expression instanceof BinaryArithmetic) {
+            BinaryArithmetic arithmetic = (BinaryArithmetic) expression;
+            fnName = arithmetic.getLegacyOperator().getName();
+            args = new DataType[]{arithmetic.left().getDataType(), 
arithmetic.right().getDataType()};
+        } else if (expression instanceof TimestampArithmetic) {
+            TimestampArithmetic arithmetic = (TimestampArithmetic) expression;
+            fnName = arithmetic.getFuncName();
+            args = new DataType[]{arithmetic.left().getDataType(), 
arithmetic.right().getDataType()};
+        }
+
+        if 
((Env.getCurrentEnv().isNullResultWithOneNullParamFunction(fnName))) {
+            for (Expression e : expression.children()) {
+                if (e instanceof NullLiteral) {
+                    return Literal.of(null);
+                }
+            }
+        }
+
+        return invoke(expression, fnName, args);
+    }
+
+    private Expression invoke(Expression expression, String fnName, DataType[] 
args) {
+        FunctionSignature signature = new FunctionSignature(fnName, args, 
null);
+        FunctionInvoker invoker = getFunction(signature);
+        if (invoker != null) {
+            try {
+                return invoker.invoke(expression.children());
+            } catch (AnalysisException e) {
+                return expression;
+            }
+        }
+        return expression;
+    }
+
+    private FunctionInvoker getFunction(FunctionSignature signature) {
+        Collection<FunctionInvoker> functionInvokers = 
functions.get(signature.getName());
+        if (functionInvokers == null) {
+            return null;
+        }
+        for (FunctionInvoker invoker : functionInvokers) {
+            DataType[] argTypes1 = invoker.getSignature().getArgTypes();
+            DataType[] argTypes2 = signature.getArgTypes();

Review Comment:
   ```suggestion
               DataType[] candidateTypes = invoker.getSignature().getArgTypes();
               DataType[] expectedTypes = signature.getArgTypes();
   ```



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnBE.java:
##########
@@ -0,0 +1,196 @@
+// 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.analysis.Expr;
+import org.apache.doris.analysis.ExprId;
+import org.apache.doris.analysis.LiteralExpr;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.PrimitiveType;
+import org.apache.doris.catalog.Type;
+import org.apache.doris.common.IdGenerator;
+import org.apache.doris.common.LoadException;
+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.trees.expressions.Between;
+import org.apache.doris.nereids.trees.expressions.Cast;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
+import org.apache.doris.nereids.types.DataType;
+import org.apache.doris.proto.InternalService;
+import org.apache.doris.proto.InternalService.PConstantExprResult;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.rpc.BackendServiceProxy;
+import org.apache.doris.system.Backend;
+import org.apache.doris.thrift.TExpr;
+import org.apache.doris.thrift.TFoldConstantParams;
+import org.apache.doris.thrift.TNetworkAddress;
+import org.apache.doris.thrift.TPrimitiveType;
+import org.apache.doris.thrift.TQueryGlobals;
+
+import com.google.common.collect.Maps;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Constant evaluation of an expression.
+ */
+public class FoldConstantRuleOnBE extends AbstractExpressionRewriteRule {
+    public static final FoldConstantRuleOnBE INSTANCE = new 
FoldConstantRuleOnBE();
+    private static final Logger LOG = 
LogManager.getLogger(FoldConstantRuleOnBE.class);
+    private static final DateTimeFormatter DATE_FORMAT = 
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    private final IdGenerator<ExprId> idGenerator = ExprId.createGenerator();
+
+    @Override
+    public Expression rewrite(Expression expr, ExpressionRewriteContext ctx) {
+        Expression expression = FoldConstantRuleOnFE.INSTANCE.rewrite(expr, 
ctx);
+        return foldByBe(expression, ctx);
+    }
+
+    private Expression foldByBe(Expression root, ExpressionRewriteContext 
context) {
+        Map<String, Expression> constMap = Maps.newHashMap();
+        Map<String, TExpr> staleConstTExprMap = Maps.newHashMap();
+        collectConst(root, constMap, staleConstTExprMap);
+        if (constMap.isEmpty()) {
+            return root;
+        }
+        Map<String, Map<String, TExpr>> paramMap = new HashMap<>();
+        paramMap.put("0", staleConstTExprMap);
+        Map<String, Expression> resultMap = evalOnBe(paramMap, constMap, 
context.connectContext);
+        if (!resultMap.isEmpty()) {
+            return replace(root, constMap, resultMap);
+        }
+        return root;
+    }
+
+    private Expression replace(Expression root, Map<String, Expression> 
constMap, Map<String, Expression> resultMap) {
+        for (Entry<String, Expression> entry : constMap.entrySet()) {
+            if (entry.getValue().equals(root)) {
+                return resultMap.get(entry.getKey());
+            }
+        }
+        List<Expression> newChildren = new ArrayList<>();
+        boolean hasNewChildren = false;
+        for (Expression child : root.children()) {
+            Expression newChild = replace(child, constMap, resultMap);
+            if (newChild != child) {
+                hasNewChildren = true;
+            }
+            newChildren.add(newChild);
+        }
+        return hasNewChildren ? root.withChildren(newChildren) : root;
+    }
+
+    private void collectConst(Expression expr, Map<String, Expression> 
constMap, Map<String, TExpr> tExprMap) {
+        if (expr.isConstant()) {
+            if (expr instanceof Cast) {
+                if (((Cast) expr).child().isNullLiteral()) {
+                    return;
+                }
+            }
+            if (expr.isLiteral()) {
+                return;
+            }
+            if (expr instanceof Between) {
+                return;
+            }
+            String id = idGenerator.getNextId().toString();
+            constMap.put(id, expr);
+            Expr staleExpr = ExpressionTranslator.translate(expr, null);
+            tExprMap.put(id, staleExpr.treeToThrift());
+        } else {
+            for (int i = 0; i < expr.children().size(); i++) {
+                final Expression child = expr.children().get(i);
+                collectConst(child, constMap, tExprMap);
+            }
+        }
+    }
+
+    private Map<String, Expression> evalOnBe(Map<String, Map<String, TExpr>> 
paramMap,
+            Map<String, Expression> constMap, ConnectContext context) {
+
+        Map<String, Expression> resultMap = new HashMap<>();
+        try {
+            List<Long> backendIds = 
Env.getCurrentSystemInfo().getBackendIds(true);
+            if (backendIds.isEmpty()) {
+                throw new LoadException("No alive backends");

Review Comment:
   why LoadException



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnFE.java:
##########
@@ -0,0 +1,310 @@
+// 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.rules.expression.rewrite.AbstractExpressionRewriteRule;
+import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.trees.expressions.And;
+import org.apache.doris.nereids.trees.expressions.BinaryArithmetic;
+import org.apache.doris.nereids.trees.expressions.CaseWhen;
+import org.apache.doris.nereids.trees.expressions.Cast;
+import org.apache.doris.nereids.trees.expressions.EqualTo;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.ExpressionEvaluator;
+import org.apache.doris.nereids.trees.expressions.GreaterThan;
+import org.apache.doris.nereids.trees.expressions.GreaterThanEqual;
+import org.apache.doris.nereids.trees.expressions.InPredicate;
+import org.apache.doris.nereids.trees.expressions.IsNull;
+import org.apache.doris.nereids.trees.expressions.LessThan;
+import org.apache.doris.nereids.trees.expressions.LessThanEqual;
+import org.apache.doris.nereids.trees.expressions.Like;
+import org.apache.doris.nereids.trees.expressions.Not;
+import org.apache.doris.nereids.trees.expressions.NullSafeEqual;
+import org.apache.doris.nereids.trees.expressions.Or;
+import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.expressions.TimestampArithmetic;
+import org.apache.doris.nereids.trees.expressions.WhenClause;
+import org.apache.doris.nereids.trees.expressions.functions.BoundFunction;
+import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable;
+import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
+import org.apache.doris.nereids.util.ExpressionUtils;
+
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * evaluate an expression on fe.
+ */
+public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
+    public static final FoldConstantRuleOnFE INSTANCE = new 
FoldConstantRuleOnFE();
+
+    @Override
+    public Expression rewrite(Expression expr, ExpressionRewriteContext ctx) {
+        return process(expr, ctx);
+    }
+
+    @Override
+    public Expression visit(Expression expr, ExpressionRewriteContext context) 
{
+        return expr;
+    }
+
+    /**
+     * process constant expression.
+     */
+    public Expression process(Expression expr, ExpressionRewriteContext ctx) {
+        if (expr instanceof PropagateNullable) {

Review Comment:
   do we need to fold children first? in other words, do a postorder traversal



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java:
##########
@@ -202,6 +207,39 @@ public static Optional<DataType> 
findTightestCommonType(DataType left, DataType
         return Optional.ofNullable(tightestCommonType);
     }
 
+    /**
+     * The type used for arithmetic operations.
+     */
+    public static DataType getNumResultType(DataType type) {
+        if (type.isTinyIntType() || type.isSmallIntType() || type.isIntType() 
|| type.isBigIntType()) {
+            return BigIntType.INSTANCE;
+        } else if (type.isLargeIntType()) {
+            return LargeIntType.INSTANCE;
+        } else if (type.isFloatType() || type.isDoubleType() || 
type.isStringType()) {
+            return DoubleType.INSTANCE;
+        } else if (type.isDecimalType()) {
+            return DecimalType.SYSTEM_DEFAULT;
+        } else if (type.isNullType()) {
+            return NullType.INSTANCE;
+        }
+        throw new AnalysisException("no found appropriate data type.");
+    }
+
+    /**
+     * The common type used by arithmetic operations.
+     */
+    public static DataType findCommonType(DataType t1, DataType t2) {

Review Comment:
   findCommonNumericsType



##########
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java:
##########
@@ -65,7 +65,7 @@ public void testNotRewrite() {
 
     @Test
     public void testNormalizeExpressionRewrite() {
-        executor = new 
ExpressionRuleExecutor(NormalizeBinaryPredicatesRule.INSTANCE);
+        executor = new 
ExpressionRuleExecutor(ImmutableList.of(NormalizeBinaryPredicatesRule.INSTANCE),
 null);

Review Comment:
   nit: add another constructor with one parameter



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ExecutableFunctions.java:
##########
@@ -0,0 +1,243 @@
+// 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.trees.expressions.functions;
+
+import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral;
+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.SmallIntLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
+import org.apache.doris.rewrite.FEFunction;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.math.BigDecimal;
+
+/**
+ * functions that can be executed in FE.
+ */
+public class ExecutableFunctions {
+    public static final ExecutableFunctions INSTANCE = new 
ExecutableFunctions();
+
+    private static final Logger LOG = 
LogManager.getLogger(ExecutableFunctions.class);
+
+    /**
+     * Executable arithmetic functions
+     */
+
+    @FEFunction(name = "add", argTypes = {"TINYINT", "TINYINT"}, returnType = 
"TINYINT")

Review Comment:
   The annotion 'FEFunction' is the one the legacy plan used? does it affect 
the legacy plan const fold?



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnBE.java:
##########
@@ -0,0 +1,196 @@
+// 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.analysis.Expr;
+import org.apache.doris.analysis.ExprId;
+import org.apache.doris.analysis.LiteralExpr;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.PrimitiveType;
+import org.apache.doris.catalog.Type;
+import org.apache.doris.common.IdGenerator;
+import org.apache.doris.common.LoadException;
+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.trees.expressions.Between;
+import org.apache.doris.nereids.trees.expressions.Cast;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
+import org.apache.doris.nereids.types.DataType;
+import org.apache.doris.proto.InternalService;
+import org.apache.doris.proto.InternalService.PConstantExprResult;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.rpc.BackendServiceProxy;
+import org.apache.doris.system.Backend;
+import org.apache.doris.thrift.TExpr;
+import org.apache.doris.thrift.TFoldConstantParams;
+import org.apache.doris.thrift.TNetworkAddress;
+import org.apache.doris.thrift.TPrimitiveType;
+import org.apache.doris.thrift.TQueryGlobals;
+
+import com.google.common.collect.Maps;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Constant evaluation of an expression.
+ */
+public class FoldConstantRuleOnBE extends AbstractExpressionRewriteRule {
+    public static final FoldConstantRuleOnBE INSTANCE = new 
FoldConstantRuleOnBE();
+    private static final Logger LOG = 
LogManager.getLogger(FoldConstantRuleOnBE.class);
+    private static final DateTimeFormatter DATE_FORMAT = 
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    private final IdGenerator<ExprId> idGenerator = ExprId.createGenerator();
+
+    @Override
+    public Expression rewrite(Expression expr, ExpressionRewriteContext ctx) {
+        Expression expression = FoldConstantRuleOnFE.INSTANCE.rewrite(expr, 
ctx);
+        return foldByBe(expression, ctx);
+    }
+
+    private Expression foldByBe(Expression root, ExpressionRewriteContext 
context) {

Review Comment:
   ```suggestion
       private Expression foldByBE(Expression root, ExpressionRewriteContext 
context) {
   ```



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnFE.java:
##########
@@ -0,0 +1,310 @@
+// 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.rules.expression.rewrite.AbstractExpressionRewriteRule;
+import 
org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
+import org.apache.doris.nereids.trees.expressions.And;
+import org.apache.doris.nereids.trees.expressions.BinaryArithmetic;
+import org.apache.doris.nereids.trees.expressions.CaseWhen;
+import org.apache.doris.nereids.trees.expressions.Cast;
+import org.apache.doris.nereids.trees.expressions.EqualTo;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.ExpressionEvaluator;
+import org.apache.doris.nereids.trees.expressions.GreaterThan;
+import org.apache.doris.nereids.trees.expressions.GreaterThanEqual;
+import org.apache.doris.nereids.trees.expressions.InPredicate;
+import org.apache.doris.nereids.trees.expressions.IsNull;
+import org.apache.doris.nereids.trees.expressions.LessThan;
+import org.apache.doris.nereids.trees.expressions.LessThanEqual;
+import org.apache.doris.nereids.trees.expressions.Like;
+import org.apache.doris.nereids.trees.expressions.Not;
+import org.apache.doris.nereids.trees.expressions.NullSafeEqual;
+import org.apache.doris.nereids.trees.expressions.Or;
+import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.expressions.TimestampArithmetic;
+import org.apache.doris.nereids.trees.expressions.WhenClause;
+import org.apache.doris.nereids.trees.expressions.functions.BoundFunction;
+import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable;
+import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
+import org.apache.doris.nereids.util.ExpressionUtils;
+
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * evaluate an expression on fe.
+ */
+public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
+    public static final FoldConstantRuleOnFE INSTANCE = new 
FoldConstantRuleOnFE();
+
+    @Override
+    public Expression rewrite(Expression expr, ExpressionRewriteContext ctx) {
+        return process(expr, ctx);
+    }
+
+    @Override
+    public Expression visit(Expression expr, ExpressionRewriteContext context) 
{
+        return expr;
+    }
+
+    /**
+     * process constant expression.
+     */
+    public Expression process(Expression expr, ExpressionRewriteContext ctx) {
+        if (expr instanceof PropagateNullable) {
+            List<Expression> children = expr.children()
+                    .stream()
+                    .map(child -> process(child, ctx))
+                    .collect(Collectors.toList());
+
+            if (ExpressionUtils.hasNullLiteral(children)) {
+                return Literal.of(null);
+            }
+
+            if (!ExpressionUtils.isAllLiteral(children)) {
+                return expr.withChildren(children);
+            }
+            return expr.withChildren(children).accept(this, ctx);
+        } else {
+            return expr.accept(this, ctx);
+        }
+    }
+
+    @Override
+    public Expression visitEqualTo(EqualTo equalTo, ExpressionRewriteContext 
context) {
+        return BooleanLiteral.of(((Literal) 
equalTo.left()).compareTo((Literal) equalTo.right()) == 0);

Review Comment:
   where to ensure all children are literal?



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionEvaluator.java:
##########
@@ -0,0 +1,210 @@
+// 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.trees.expressions;
+
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.AnalysisException;
+import 
org.apache.doris.nereids.trees.expressions.functions.ExecutableFunctions;
+import 
org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
+import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
+import org.apache.doris.nereids.types.DataType;
+import org.apache.doris.rewrite.FEFunction;
+import org.apache.doris.rewrite.FEFunctionList;
+
+import com.google.common.collect.ImmutableMultimap;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * An expression evaluator that evaluates the value of an expression.
+ */
+public enum ExpressionEvaluator {
+    INSTANCE;
+    private ImmutableMultimap<String, FunctionInvoker> functions;
+
+    ExpressionEvaluator() {
+        registerFunctions();
+    }
+
+    /**
+     * Evaluate the value of the expression.
+     */
+    public Expression eval(Expression expression) {
+
+        if (!expression.isConstant() || expression instanceof 
AggregateFunction) {
+            return expression;
+        }
+
+        String fnName = null;
+        DataType[] args = null;
+        if (expression instanceof BinaryArithmetic) {
+            BinaryArithmetic arithmetic = (BinaryArithmetic) expression;
+            fnName = arithmetic.getLegacyOperator().getName();
+            args = new DataType[]{arithmetic.left().getDataType(), 
arithmetic.right().getDataType()};
+        } else if (expression instanceof TimestampArithmetic) {
+            TimestampArithmetic arithmetic = (TimestampArithmetic) expression;
+            fnName = arithmetic.getFuncName();
+            args = new DataType[]{arithmetic.left().getDataType(), 
arithmetic.right().getDataType()};
+        }
+
+        if 
((Env.getCurrentEnv().isNullResultWithOneNullParamFunction(fnName))) {
+            for (Expression e : expression.children()) {
+                if (e instanceof NullLiteral) {
+                    return Literal.of(null);
+                }
+            }
+        }
+
+        return invoke(expression, fnName, args);
+    }
+
+    private Expression invoke(Expression expression, String fnName, DataType[] 
args) {
+        FunctionSignature signature = new FunctionSignature(fnName, args, 
null);
+        FunctionInvoker invoker = getFunction(signature);
+        if (invoker != null) {
+            try {
+                return invoker.invoke(expression.children());
+            } catch (AnalysisException e) {
+                return expression;
+            }
+        }
+        return expression;
+    }
+
+    private FunctionInvoker getFunction(FunctionSignature signature) {
+        Collection<FunctionInvoker> functionInvokers = 
functions.get(signature.getName());
+        if (functionInvokers == null) {
+            return null;
+        }
+        for (FunctionInvoker invoker : functionInvokers) {

Review Comment:
   ```suggestion
           for (FunctionInvoker candidate : functionInvokers) {
   ```



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/FoldConstantRuleOnBE.java:
##########
@@ -0,0 +1,196 @@
+// 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.analysis.Expr;
+import org.apache.doris.analysis.ExprId;
+import org.apache.doris.analysis.LiteralExpr;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.PrimitiveType;
+import org.apache.doris.catalog.Type;
+import org.apache.doris.common.IdGenerator;
+import org.apache.doris.common.LoadException;
+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.trees.expressions.Between;
+import org.apache.doris.nereids.trees.expressions.Cast;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
+import org.apache.doris.nereids.types.DataType;
+import org.apache.doris.proto.InternalService;
+import org.apache.doris.proto.InternalService.PConstantExprResult;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.rpc.BackendServiceProxy;
+import org.apache.doris.system.Backend;
+import org.apache.doris.thrift.TExpr;
+import org.apache.doris.thrift.TFoldConstantParams;
+import org.apache.doris.thrift.TNetworkAddress;
+import org.apache.doris.thrift.TPrimitiveType;
+import org.apache.doris.thrift.TQueryGlobals;
+
+import com.google.common.collect.Maps;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Constant evaluation of an expression.
+ */
+public class FoldConstantRuleOnBE extends AbstractExpressionRewriteRule {
+    public static final FoldConstantRuleOnBE INSTANCE = new 
FoldConstantRuleOnBE();
+    private static final Logger LOG = 
LogManager.getLogger(FoldConstantRuleOnBE.class);
+    private static final DateTimeFormatter DATE_FORMAT = 
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    private final IdGenerator<ExprId> idGenerator = ExprId.createGenerator();
+
+    @Override
+    public Expression rewrite(Expression expr, ExpressionRewriteContext ctx) {
+        Expression expression = FoldConstantRuleOnFE.INSTANCE.rewrite(expr, 
ctx);
+        return foldByBe(expression, ctx);
+    }
+
+    private Expression foldByBe(Expression root, ExpressionRewriteContext 
context) {
+        Map<String, Expression> constMap = Maps.newHashMap();
+        Map<String, TExpr> staleConstTExprMap = Maps.newHashMap();
+        collectConst(root, constMap, staleConstTExprMap);
+        if (constMap.isEmpty()) {
+            return root;
+        }
+        Map<String, Map<String, TExpr>> paramMap = new HashMap<>();
+        paramMap.put("0", staleConstTExprMap);
+        Map<String, Expression> resultMap = evalOnBe(paramMap, constMap, 
context.connectContext);
+        if (!resultMap.isEmpty()) {
+            return replace(root, constMap, resultMap);
+        }
+        return root;
+    }
+
+    private Expression replace(Expression root, Map<String, Expression> 
constMap, Map<String, Expression> resultMap) {
+        for (Entry<String, Expression> entry : constMap.entrySet()) {
+            if (entry.getValue().equals(root)) {
+                return resultMap.get(entry.getKey());
+            }
+        }
+        List<Expression> newChildren = new ArrayList<>();
+        boolean hasNewChildren = false;
+        for (Expression child : root.children()) {
+            Expression newChild = replace(child, constMap, resultMap);
+            if (newChild != child) {
+                hasNewChildren = true;
+            }
+            newChildren.add(newChild);
+        }
+        return hasNewChildren ? root.withChildren(newChildren) : root;
+    }
+
+    private void collectConst(Expression expr, Map<String, Expression> 
constMap, Map<String, TExpr> tExprMap) {
+        if (expr.isConstant()) {
+            if (expr instanceof Cast) {

Review Comment:
   nit: add some comment to describe why need to process these expr specially



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


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


Reply via email to