alamb commented on a change in pull request #1128:
URL: https://github.com/apache/arrow-datafusion/pull/1128#discussion_r731283571



##########
File path: datafusion/src/optimizer/utils.rs
##########
@@ -468,6 +473,117 @@ pub fn rewrite_expression(expr: &Expr, expressions: 
&[Expr]) -> Result<Expr> {
     }
 }
 
+///Tests an expression to see if it contains only literal expressions such as 
3+4.5 and immutable scalar builtins or UDFs.
+pub fn expr_is_const(expr: &Expr) -> bool {
+    match expr {
+        Expr::Column(_)
+        | Expr::ScalarVariable(_)
+        | Expr::AggregateFunction { .. }
+        | Expr::WindowFunction { .. }
+        | Expr::AggregateUDF { .. }
+        | Expr::Sort { .. }
+        | Expr::Wildcard => false,
+
+        Expr::Literal(_) => true,
+
+        Expr::Alias(child, _)
+        | Expr::Not(child)
+        | Expr::IsNotNull(child)
+        | Expr::IsNull(child)
+        | Expr::Negative(child)
+        | Expr::Cast { expr: child, .. }
+        | Expr::TryCast { expr: child, .. } => expr_is_const(child),
+
+        Expr::ScalarFunction { fun, args } => match fun.volatility() {
+            Volatility::Immutable => args.iter().all(|arg| expr_is_const(arg)),
+            Volatility::Stable | Volatility::Volatile => false,
+        },
+        Expr::BinaryExpr { left, right, .. } => {
+            expr_is_const(left) && expr_is_const(right)
+        }
+        Expr::Between {
+            expr, low, high, ..
+        } => expr_is_const(expr) && expr_is_const(low) && expr_is_const(high),
+        Expr::Case {
+            expr,
+            when_then_expr,
+            else_expr,
+        } => {
+            let expr_constant = expr.as_ref().map(|e| 
expr_is_const(e)).unwrap_or(true);
+            let else_constant =
+                else_expr.as_ref().map(|e| expr_is_const(e)).unwrap_or(true);
+            let when_then_constant = when_then_expr
+                .iter()
+                .all(|(w, th)| expr_is_const(w) && expr_is_const(th));
+            expr_constant && else_constant && when_then_constant
+        }
+
+        Expr::ScalarUDF { fun, args } => match fun.volatility() {
+            Volatility::Immutable => args.iter().all(|arg| expr_is_const(arg)),
+            Volatility::Stable | Volatility::Volatile => false,
+        },
+
+        Expr::InList { expr, list, .. } => {
+            expr_is_const(expr) && list.iter().all(|e| expr_is_const(e))
+        }
+    }
+}
+
+///Evaluates an expression if it only contains literal expressions. If a 
non-literal expression or non-immutable function is found then it returns an 
error.

Review comment:
       I suggest the public API should be something like:
   
   ```rust
   partially_evaluate_expr(expr: &Expr)
   ```
   or
   ```rust
   Expr::partially_evaluate(self) -> Self
   ```
   




-- 
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: github-unsubscr...@arrow.apache.org

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


Reply via email to