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