kosiew commented on code in PR #25143:
URL: https://github.com/apache/datafusion/pull/25143#discussion_r3988603167


##########
datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs:
##########
@@ -2432,6 +2436,26 @@ fn simplify_inlist_set_operation(
     }))
 }
 
+/// Conservatively checks the inputs whose evaluation can change when lowering
+/// CASE to AND/OR. [`Expr`] has no general fallibility analysis: only columns 
and
+/// literals are admitted from conditional branches, including later WHEN 
conditions.
+/// The first WHEN already runs on every row, but must not be volatile because
+/// the rewrite can evaluate it more than once.
+fn can_lower_case_to_boolean(
+    when_then_expr: &[(Box<Expr>, Box<Expr>)],
+    else_expr: Option<&Expr>,
+) -> bool {
+    let is_leaf = |expr: &Expr| matches!(expr, Expr::Column(_) | 
Expr::Literal(..));
+    when_then_expr.iter().enumerate().all(|(i, (when, then))| {
+        is_leaf(then)
+            && if i == 0 {
+                !when.is_volatile()

Review Comment:
   I think there is still a correctness issue with allowing the first `WHEN` as 
long as it is non-volatile. It can still fail, and the Boolean rewrite can 
eliminate its evaluation entirely.
   
   For example, `SELECT CASE WHEN CAST(s AS INT) > 0 THEN false ELSE false END 
FROM (VALUES ('abc')) t(s)` should raise the cast error because CASE evaluates 
its first WHEN for every row. With this rewrite, both branches can simplify to 
`false`, so the condition is never evaluated and the query returns `false` 
instead.
   
   Could we require the first `WHEN` to be a column or literal as well, unless 
we add a sound fallibility analysis? It would also be good to add this example 
as a regression test, particularly with identical literal results so we cover 
the case where simplification removes the condition.



##########
datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs:
##########
@@ -2432,6 +2436,26 @@ fn simplify_inlist_set_operation(
     }))
 }
 
+/// Conservatively checks the inputs whose evaluation can change when lowering
+/// CASE to AND/OR. [`Expr`] has no general fallibility analysis: only columns 
and
+/// literals are admitted from conditional branches, including later WHEN 
conditions.

Review Comment:
   Once the first-WHEN guard is tightened, could we update this comment to 
match the invariant and say that all `WHEN` conditions and branch outputs must 
be columns or literals? I think spelling that out here will make it less likely 
that a future special case accidentally reintroduces this error-preservation 
gap.



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to