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

liurenjie1024 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-rust.git


The following commit(s) were added to refs/heads/main by this push:
     new 7666bb6  Simplify expression when doing `{and,or}` operations (#339)
7666bb6 is described below

commit 7666bb6766c0e751ff90092f2d2fd7c362d76c67
Author: Fokko Driesprong <[email protected]>
AuthorDate: Fri Apr 19 16:43:46 2024 +0200

    Simplify expression when doing `{and,or}` operations (#339)
    
    This will make sure that we nicely reduce the expression in
    the inclusive projection visitor:
    
    
https://github.com/apache/iceberg-rust/blob/de80a2436bb2fbbd5b4ec6bcafd0bd041b263595/crates/iceberg/src/expr/visitors/inclusive_projection.rs#L73
---
 crates/iceberg/src/expr/predicate.rs | 53 ++++++++++++++++++++++++++++++++++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/crates/iceberg/src/expr/predicate.rs 
b/crates/iceberg/src/expr/predicate.rs
index 1163f3b..6cdf4fc 100644
--- a/crates/iceberg/src/expr/predicate.rs
+++ b/crates/iceberg/src/expr/predicate.rs
@@ -456,7 +456,13 @@ impl Predicate {
     /// assert_eq!(&format!("{expr}"), "(a < 10) AND (b < 20)");
     /// ```
     pub fn and(self, other: Predicate) -> Predicate {
-        Predicate::And(LogicalExpression::new([Box::new(self), 
Box::new(other)]))
+        match (self, other) {
+            (Predicate::AlwaysFalse, _) => Predicate::AlwaysFalse,
+            (_, Predicate::AlwaysFalse) => Predicate::AlwaysFalse,
+            (Predicate::AlwaysTrue, rhs) => rhs,
+            (lhs, Predicate::AlwaysTrue) => lhs,
+            (lhs, rhs) => 
Predicate::And(LogicalExpression::new([Box::new(lhs), Box::new(rhs)])),
+        }
     }
 
     /// Combines two predicates with `OR`.
@@ -477,7 +483,13 @@ impl Predicate {
     /// assert_eq!(&format!("{expr}"), "(a < 10) OR (b < 20)");
     /// ```
     pub fn or(self, other: Predicate) -> Predicate {
-        Predicate::Or(LogicalExpression::new([Box::new(self), 
Box::new(other)]))
+        match (self, other) {
+            (Predicate::AlwaysTrue, _) => Predicate::AlwaysTrue,
+            (_, Predicate::AlwaysTrue) => Predicate::AlwaysTrue,
+            (Predicate::AlwaysFalse, rhs) => rhs,
+            (lhs, Predicate::AlwaysFalse) => lhs,
+            (lhs, rhs) => Predicate::Or(LogicalExpression::new([Box::new(lhs), 
Box::new(rhs)])),
+        }
     }
 
     /// Returns a predicate representing the negation ('NOT') of this one,
@@ -658,6 +670,7 @@ mod tests {
     use std::sync::Arc;
 
     use crate::expr::Bind;
+    use crate::expr::Predicate::{AlwaysFalse, AlwaysTrue};
     use crate::expr::Reference;
     use crate::spec::Datum;
     use crate::spec::{NestedField, PrimitiveType, Schema, SchemaRef, Type};
@@ -729,6 +742,42 @@ mod tests {
         assert_eq!(result, expected);
     }
 
+    #[test]
+    fn test_predicate_and_reduce_always_true_false() {
+        let true_or_expr = 
AlwaysTrue.and(Reference::new("b").less_than(Datum::long(5)));
+        assert_eq!(&format!("{true_or_expr}"), "b < 5");
+
+        let expr_or_true = Reference::new("b")
+            .less_than(Datum::long(5))
+            .and(AlwaysTrue);
+        assert_eq!(&format!("{expr_or_true}"), "b < 5");
+
+        let false_or_expr = 
AlwaysFalse.and(Reference::new("b").less_than(Datum::long(5)));
+        assert_eq!(&format!("{false_or_expr}"), "FALSE");
+
+        let expr_or_false = Reference::new("b")
+            .less_than(Datum::long(5))
+            .and(AlwaysFalse);
+        assert_eq!(&format!("{expr_or_false}"), "FALSE");
+    }
+
+    #[test]
+    fn test_predicate_or_reduce_always_true_false() {
+        let true_or_expr = 
AlwaysTrue.or(Reference::new("b").less_than(Datum::long(5)));
+        assert_eq!(&format!("{true_or_expr}"), "TRUE");
+
+        let expr_or_true = 
Reference::new("b").less_than(Datum::long(5)).or(AlwaysTrue);
+        assert_eq!(&format!("{expr_or_true}"), "TRUE");
+
+        let false_or_expr = 
AlwaysFalse.or(Reference::new("b").less_than(Datum::long(5)));
+        assert_eq!(&format!("{false_or_expr}"), "b < 5");
+
+        let expr_or_false = Reference::new("b")
+            .less_than(Datum::long(5))
+            .or(AlwaysFalse);
+        assert_eq!(&format!("{expr_or_false}"), "b < 5");
+    }
+
     #[test]
     fn test_predicate_negate_and() {
         let expression = Reference::new("b")

Reply via email to