kangkaisen commented on a change in pull request #255: Simplify constant Expr
URL: https://github.com/apache/incubator-doris/pull/255#discussion_r230672079
 
 

 ##########
 File path: fe/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java
 ##########
 @@ -0,0 +1,233 @@
+// 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.rewrite;
+
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.apache.doris.analysis.Analyzer;
+import org.apache.doris.analysis.ArithmeticExpr;
+import org.apache.doris.analysis.CastExpr;
+import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.FunctionCallExpr;
+import org.apache.doris.analysis.LiteralExpr;
+import org.apache.doris.analysis.NullLiteral;
+import org.apache.doris.catalog.Function;
+import org.apache.doris.catalog.ScalarType;
+import org.apache.doris.catalog.Type;
+import org.apache.doris.common.AnalysisException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * This rule replaces a constant Expr with its equivalent LiteralExpr by 
evaluating the
+ * Expr in the BE. Exprs that are already LiteralExprs are not changed.
+ *
+ * TODO: Expressions fed into this rule are currently not required to be 
analyzed
+ * in order to support constant folding in expressions that contain unresolved
+ * references to select-list aliases (such expressions cannot be analyzed).
+ * The cross-dependencies between rule transformations and analysis are vague 
at the
+ * moment and make rule application overly complicated.
+ *
+ * Examples:
+ * 1 + 1 + 1 --> 3
+ * toupper('abc') --> 'ABC'
+ * cast('2016-11-09' as timestamp) --> TIMESTAMP '2016-11-09 00:00:00'
+ */
+public class FoldConstantsRule implements ExprRewriteRule {
+    public static ExprRewriteRule INSTANCE = new FoldConstantsRule();
+
+    private Multimap<String, FEFunctionInvoker> functions = 
ArrayListMultimap.create();
+
+    @Override
+    public Expr apply(Expr expr, Analyzer analyzer) throws AnalysisException {
+        if (functions.isEmpty()) {
+            registerFunctions();
+        }
+
+        // Avoid calling Expr.isConstant() because that would lead to repeated 
traversals
+        // of the Expr tree. Assumes the bottom-up application of this rule. 
Constant
+        // children should have been folded at this point.
+        for (Expr child : expr.getChildren()) {
+            if (!child.isLiteral() && !(child instanceof CastExpr)) {
+                return expr;
+            }
+        }
+
+        if (expr.isLiteral() || !expr.isConstant()) {
+            return expr;
+        }
+
+        // Do not constant fold cast(null as dataType) because we cannot 
preserve the
+        // cast-to-types and that can lead to query failures, e.g., CTAS
+        if (expr instanceof CastExpr) {
+            CastExpr castExpr = (CastExpr) expr;
+            if (castExpr.getChild(0) instanceof NullLiteral) {
+                return expr;
+            }
+        }
+        // Analyze constant exprs, if necessary. Note that the 'expr' may 
become non-constant
+        // after analysis (e.g., aggregate functions).
+        if (!expr.isAnalyzed()) {
+            expr.analyze(analyzer);
+            if (!expr.isConstant()) {
+                return expr;
+            }
+        }
+        return simplify(expr);
+    }
+
+    private Expr simplify(Expr constExpr) throws AnalysisException {
+        if (constExpr instanceof ArithmeticExpr
+                || constExpr instanceof FunctionCallExpr
+                || constExpr instanceof CastExpr) {
+            Function fn = constExpr.getFn();
+            List<ScalarType> argTypes = new ArrayList<>();
+            for (Type type : fn.getArgs()) {
+                argTypes.add((ScalarType) type);
+            }
+            FEFunctionSignature signature = new 
FEFunctionSignature(fn.functionName(),
+                    argTypes.toArray(new ScalarType[argTypes.size()]), 
(ScalarType) fn.getReturnType());
+            FEFunctionInvoker invoker = getFunction(signature);
+            if (invoker != null) {
+                try {
+                    return invoker.invoke(constExpr.getChildrenWithoutCast());
+                } catch (AnalysisException e) {
+                    return constExpr;
+                }
+            }
+        }
+        return constExpr;
+    }
+
+    private FEFunctionInvoker getFunction(FEFunctionSignature signature) {
+        Collection<FEFunctionInvoker> functionInvokers = 
functions.get(signature.getName());
+
+        if (functionInvokers == null) {
+            return null;
+        }
+
+        for (FEFunctionInvoker invoker : functionInvokers) {
+            if 
(!invoker.getSignature().returnType.equals(signature.getReturnType())) {
+                continue;
+            }
+
+            ScalarType[] argTypes1 = invoker.getSignature().getArgTypes();
+            ScalarType[] argTypes2 = signature.getArgTypes();
+
+            if (!Arrays.equals(argTypes1, argTypes2)) {
+                continue;
+            }
+
+            return invoker;
+        }
+        return null;
+    }
+
+    private void registerFunctions() {
 
 Review comment:
   Yes.  Fixed.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

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

Reply via email to