This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new e661b33ee3 Correct implementations of `NullableInterval::and` and 
`NullableInterval::or`. (#18625)
e661b33ee3 is described below

commit e661b33ee3b96d045fa8cd2533c2a54c07ac7488
Author: Pepijn Van Eeckhoudt <[email protected]>
AuthorDate: Wed Nov 12 15:57:45 2025 +0100

    Correct implementations of `NullableInterval::and` and 
`NullableInterval::or`. (#18625)
    
    ## Which issue does this PR close?
    
    - Closes #18626.
    
    ## Rationale for this change
    
    The boolean interval arithmetic implemented by `NullableInterval` should
    match that of SQL.
    
    ## What changes are included in this PR?
    
    - Add unit tests covering all possible permutations of `and`, `or` and
    `not` on `NullableInterval`
    - Add `NullableInterval` constants for boolean intervals
    - Add `NullableInterval::and` and `NullableInterval::or` implementations
    that match SQL
    - Delegate to `and` and `or` in `NullableInterval::apply_operator`
    
    ## Are these changes tested?
    
    Yes, tests have been added that cover all possible combinations
    
    ## Are there any user-facing changes?
    
    No
    
    Co-authored-by: Andrew Lamb <[email protected]>
---
 datafusion/expr-common/src/interval_arithmetic.rs | 676 +++++++++++++++++++++-
 1 file changed, 664 insertions(+), 12 deletions(-)

diff --git a/datafusion/expr-common/src/interval_arithmetic.rs 
b/datafusion/expr-common/src/interval_arithmetic.rs
index bbf14da1eb..942f3d48c6 100644
--- a/datafusion/expr-common/src/interval_arithmetic.rs
+++ b/datafusion/expr-common/src/interval_arithmetic.rs
@@ -1738,6 +1738,44 @@ impl From<ScalarValue> for NullableInterval {
 }
 
 impl NullableInterval {
+    /// An interval that only contains 'false'.
+    pub const FALSE: Self = NullableInterval::NotNull {
+        values: Interval::CERTAINLY_FALSE,
+    };
+
+    /// An interval that only contains 'true'.
+    pub const TRUE: Self = NullableInterval::NotNull {
+        values: Interval::CERTAINLY_TRUE,
+    };
+
+    /// An interval that only contains 'unknown' (boolean null).
+    pub const UNKNOWN: Self = NullableInterval::Null {
+        datatype: DataType::Boolean,
+    };
+
+    /// An interval that only contains 'true' and 'false'.
+    /// This interval is equivalent to [Interval::UNCERTAIN].
+    pub const TRUE_OR_FALSE: Self = NullableInterval::NotNull {
+        values: Interval::UNCERTAIN,
+    };
+
+    /// An interval that only contains 'true' and 'unknown'.
+    pub const TRUE_OR_UNKNOWN: Self = NullableInterval::MaybeNull {
+        values: Interval::CERTAINLY_TRUE,
+    };
+
+    /// An interval that only contains 'false' and 'unknown'.
+    pub const FALSE_OR_UNKNOWN: Self = NullableInterval::MaybeNull {
+        values: Interval::CERTAINLY_FALSE,
+    };
+
+    /// An interval that contains all possible boolean values: 'true', 'false' 
and 'unknown'.
+    ///
+    /// Note that this is different from [Interval::UNCERTAIN] which only 
contains 'true' and 'false'.
+    pub const UNCERTAIN: Self = NullableInterval::MaybeNull {
+        values: Interval::UNCERTAIN,
+    };
+
     /// Get the values interval, or None if this interval is definitely null.
     pub fn values(&self) -> Option<&Interval> {
         match self {
@@ -1756,27 +1794,31 @@ impl NullableInterval {
 
     /// Return true if the value is definitely true (and not null).
     pub fn is_certainly_true(&self) -> bool {
-        match self {
-            Self::Null { .. } | Self::MaybeNull { .. } => false,
-            Self::NotNull { values } => values == &Interval::CERTAINLY_TRUE,
-        }
+        self == &Self::TRUE
     }
 
     /// Return true if the value is definitely false (and not null).
     pub fn is_certainly_false(&self) -> bool {
-        match self {
-            Self::Null { .. } => false,
-            Self::MaybeNull { .. } => false,
-            Self::NotNull { values } => values == &Interval::CERTAINLY_FALSE,
-        }
+        self == &Self::FALSE
+    }
+
+    /// Return true if the value is definitely null (and not true or false).
+    pub fn is_certainly_unknown(&self) -> bool {
+        self == &Self::UNKNOWN
     }
 
     /// Perform logical negation on a boolean nullable interval.
     fn not(&self) -> Result<Self> {
         match self {
-            Self::Null { datatype } => Ok(Self::Null {
-                datatype: datatype.clone(),
-            }),
+            Self::Null { datatype } => {
+                if datatype == &DataType::Boolean {
+                    Ok(Self::UNKNOWN)
+                } else {
+                    internal_err!(
+                        "Cannot apply logical negation to a non-boolean 
interval"
+                    )
+                }
+            }
             Self::MaybeNull { values } => Ok(Self::MaybeNull {
                 values: values.not()?,
             }),
@@ -1786,6 +1828,62 @@ impl NullableInterval {
         }
     }
 
+    /// Compute the logical conjunction of this (boolean) interval with the
+    /// given boolean interval.
+    pub fn and<T: Borrow<Self>>(&self, rhs: T) -> Result<Self> {
+        if self == &Self::FALSE || rhs.borrow() == &Self::FALSE {
+            return Ok(Self::FALSE);
+        }
+
+        match (self.values(), rhs.borrow().values()) {
+            (Some(l), Some(r)) => {
+                let values = l.and(r)?;
+                match (self, rhs.borrow()) {
+                    (Self::NotNull { .. }, Self::NotNull { .. }) => {
+                        Ok(Self::NotNull { values })
+                    }
+                    _ => Ok(Self::MaybeNull { values }),
+                }
+            }
+            (Some(v), None) | (None, Some(v)) => {
+                if v.contains_value(ScalarValue::Boolean(Some(false)))? {
+                    Ok(Self::FALSE_OR_UNKNOWN)
+                } else {
+                    Ok(Self::UNKNOWN)
+                }
+            }
+            _ => Ok(Self::UNKNOWN),
+        }
+    }
+
+    /// Compute the logical disjunction of this (boolean) interval with the
+    /// given boolean interval.
+    pub fn or<T: Borrow<Self>>(&self, rhs: T) -> Result<Self> {
+        if self == &Self::TRUE || rhs.borrow() == &Self::TRUE {
+            return Ok(Self::TRUE);
+        }
+
+        match (self.values(), rhs.borrow().values()) {
+            (Some(l), Some(r)) => {
+                let values = l.or(r)?;
+                match (self, rhs.borrow()) {
+                    (Self::NotNull { .. }, Self::NotNull { .. }) => {
+                        Ok(Self::NotNull { values })
+                    }
+                    _ => Ok(Self::MaybeNull { values }),
+                }
+            }
+            (Some(v), None) | (None, Some(v)) => {
+                if v.contains_value(ScalarValue::Boolean(Some(true)))? {
+                    Ok(Self::TRUE_OR_UNKNOWN)
+                } else {
+                    Ok(Self::UNKNOWN)
+                }
+            }
+            _ => Ok(Self::UNKNOWN),
+        }
+    }
+
     /// Apply the given operator to this interval and the given interval.
     ///
     /// # Examples
@@ -1869,6 +1967,8 @@ impl NullableInterval {
             Operator::IsNotDistinctFrom => self
                 .apply_operator(&Operator::IsDistinctFrom, rhs)
                 .map(|i| i.not())?,
+            Operator::And => self.and(rhs),
+            Operator::Or => self.or(rhs),
             _ => {
                 if let (Some(left_values), Some(right_values)) =
                     (self.values(), rhs.values())
@@ -1967,6 +2067,7 @@ mod tests {
         operator::Operator,
     };
 
+    use crate::interval_arithmetic::NullableInterval;
     use arrow::datatypes::DataType;
     use datafusion_common::rounding::{next_down, next_up};
     use datafusion_common::{Result, ScalarValue};
@@ -4226,4 +4327,555 @@ mod tests {
 
         Ok(())
     }
+
+    #[test]
+    fn nullable_and_test() -> Result<()> {
+        let cases = vec![
+            (
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::TRUE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::UNKNOWN,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::TRUE,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE_OR_FALSE,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::TRUE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+        ];
+
+        for case in cases {
+            assert_eq!(
+                case.0.apply_operator(&Operator::And, &case.1).unwrap(),
+                case.2,
+                "Failed for {} AND {}",
+                case.0,
+                case.1
+            );
+        }
+        Ok(())
+    }
+
+    #[test]
+    fn nullable_or_test() -> Result<()> {
+        let cases = vec![
+            (
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::FALSE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::TRUE,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+                NullableInterval::FALSE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::FALSE,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::FALSE,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::FALSE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::TRUE,
+                NullableInterval::TRUE,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::UNKNOWN,
+                NullableInterval::UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::UNCERTAIN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::UNCERTAIN,
+                NullableInterval::UNCERTAIN,
+            ),
+        ];
+
+        for case in cases {
+            assert_eq!(
+                case.0.apply_operator(&Operator::Or, &case.1).unwrap(),
+                case.2,
+                "Failed for {} OR {}",
+                case.0,
+                case.1
+            );
+        }
+        Ok(())
+    }
+
+    #[test]
+    fn nullable_not_test() -> Result<()> {
+        let cases = vec![
+            (NullableInterval::TRUE, NullableInterval::FALSE),
+            (NullableInterval::FALSE, NullableInterval::TRUE),
+            (NullableInterval::UNKNOWN, NullableInterval::UNKNOWN),
+            (
+                NullableInterval::TRUE_OR_FALSE,
+                NullableInterval::TRUE_OR_FALSE,
+            ),
+            (
+                NullableInterval::TRUE_OR_UNKNOWN,
+                NullableInterval::FALSE_OR_UNKNOWN,
+            ),
+            (
+                NullableInterval::FALSE_OR_UNKNOWN,
+                NullableInterval::TRUE_OR_UNKNOWN,
+            ),
+            (NullableInterval::UNCERTAIN, NullableInterval::UNCERTAIN),
+        ];
+
+        for case in cases {
+            assert_eq!(case.0.not().unwrap(), case.1, "Failed for NOT {}", 
case.0,);
+        }
+        Ok(())
+    }
 }


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

Reply via email to