1515// specific language governing permissions and limitations 
1616// under the License. 
1717
18- use  crate :: expressions:: try_cast; 
18+ use  crate :: expressions:: { try_cast,   BinaryExpr ,   IsNotNullExpr ,   NotExpr } ; 
1919use  crate :: PhysicalExpr ; 
20- use  std:: borrow:: Cow ; 
21- use  std:: hash:: Hash ; 
22- use  std:: { any:: Any ,  sync:: Arc } ; 
23- 
2420use  arrow:: array:: * ; 
2521use  arrow:: compute:: kernels:: zip:: zip; 
2622use  arrow:: compute:: { and,  and_not,  is_null,  not,  nullif,  or,  prep_null_mask_filter} ; 
@@ -30,8 +26,12 @@ use datafusion_common::{
3026    exec_err,  internal_datafusion_err,  internal_err,  DataFusionError ,  Result ,  ScalarValue , 
3127} ; 
3228use  datafusion_expr:: ColumnarValue ; 
29+ use  std:: borrow:: Cow ; 
30+ use  std:: hash:: Hash ; 
31+ use  std:: { any:: Any ,  sync:: Arc } ; 
3332
3433use  super :: { Column ,  Literal } ; 
34+ use  datafusion_expr_common:: operator:: Operator ; 
3535use  datafusion_physical_expr_common:: datum:: compare_with_eq; 
3636use  itertools:: Itertools ; 
3737
@@ -481,6 +481,9 @@ impl PhysicalExpr for CaseExpr {
481481        let  then_nullable = self 
482482            . when_then_expr 
483483            . iter ( ) 
484+             . filter ( |( w,  t) | { 
485+                 !always_false_when_value_is_null ( w. as_ref ( ) ,  t. as_ref ( ) ) . unwrap_or ( false ) 
486+             } ) 
484487            . map ( |( _,  t) | t. nullable ( input_schema) ) 
485488            . collect :: < Result < Vec < _ > > > ( ) ?; 
486489        if  then_nullable. contains ( & true )  { 
@@ -588,6 +591,40 @@ impl PhysicalExpr for CaseExpr {
588591    } 
589592} 
590593
594+ fn  always_false_when_value_is_null ( 
595+     predicate :  & dyn  PhysicalExpr , 
596+     value :  & dyn  PhysicalExpr , 
597+ )  -> Option < bool >  { 
598+     let  predicate_any = predicate. as_any ( ) ; 
599+     if  let  Some ( not_null)  = predicate_any. downcast_ref :: < IsNotNullExpr > ( )  { 
600+         Some ( not_null. arg ( ) . as_ref ( ) . dyn_eq ( value) ) 
601+     }  else  if  let  Some ( not)  = predicate_any. downcast_ref :: < NotExpr > ( )  { 
602+         always_false_when_value_is_null ( not. arg ( ) . as_ref ( ) ,  value) . map ( |b| !b) 
603+     }  else  if  let  Some ( binary)  = predicate_any. downcast_ref :: < BinaryExpr > ( )  { 
604+         match  binary. op ( )  { 
605+             Operator :: And  => { 
606+                 let  l = always_false_when_value_is_null ( binary. left ( ) . as_ref ( ) ,  value) ; 
607+                 let  r = always_false_when_value_is_null ( binary. right ( ) . as_ref ( ) ,  value) ; 
608+                 match  ( l,  r)  { 
609+                     ( Some ( l) ,  Some ( r) )  => Some ( l || r) , 
610+                     _ => None , 
611+                 } 
612+             } 
613+             Operator :: Or  => { 
614+                 let  l = always_false_when_value_is_null ( binary. left ( ) . as_ref ( ) ,  value) ; 
615+                 let  r = always_false_when_value_is_null ( binary. right ( ) . as_ref ( ) ,  value) ; 
616+                 match  ( l,  r)  { 
617+                     ( Some ( l) ,  Some ( r) )  => Some ( l && r) , 
618+                     _ => None , 
619+                 } 
620+             } 
621+             _ => None , 
622+         } 
623+     }  else  { 
624+         None 
625+     } 
626+ } 
627+ 
591628/// Create a CASE expression 
592629pub  fn  case ( 
593630    expr :  Option < Arc < dyn  PhysicalExpr > > , 
0 commit comments