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 94c9af0 feat: Complete predicate builders for all operators. (#276)
94c9af0 is described below
commit 94c9af08d4f8a56c820655b212f94d62da949e3a
Author: QuakeWang <[email protected]>
AuthorDate: Wed Mar 27 11:54:03 2024 +0800
feat: Complete predicate builders for all operators. (#276)
* feat: Complete predicate builders for all operators.
* ci: fix fmt error
* fix nan and notnan
---
crates/iceberg/src/expr/predicate.rs | 134 ++++++++++++++++++++++++++++++++
crates/iceberg/src/expr/term.rs | 145 +++++++++++++++++++++++++++++++++++
2 files changed, 279 insertions(+)
diff --git a/crates/iceberg/src/expr/predicate.rs
b/crates/iceberg/src/expr/predicate.rs
index f8bcffe..da8a863 100644
--- a/crates/iceberg/src/expr/predicate.rs
+++ b/crates/iceberg/src/expr/predicate.rs
@@ -769,6 +769,7 @@ mod tests {
NestedField::optional(1, "foo",
Type::Primitive(PrimitiveType::String)).into(),
NestedField::required(2, "bar",
Type::Primitive(PrimitiveType::Int)).into(),
NestedField::optional(3, "baz",
Type::Primitive(PrimitiveType::Boolean)).into(),
+ NestedField::optional(4, "qux",
Type::Primitive(PrimitiveType::Float)).into(),
])
.build()
.unwrap(),
@@ -807,6 +808,43 @@ mod tests {
assert_eq!(&format!("{bound_expr}"), "True");
}
+ #[test]
+ fn test_bind_is_nan() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("qux").is_nan();
+ let bound_expr = expr.bind(schema, true).unwrap();
+ assert_eq!(&format!("{bound_expr}"), "qux IS NAN");
+
+ let schema_string = table_schema_simple();
+ let expr_string = Reference::new("foo").is_nan();
+ let bound_expr_string = expr_string.bind(schema_string, true);
+ assert!(bound_expr_string.is_err());
+ }
+
+ #[test]
+ fn test_bind_is_nan_wrong_type() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("foo").is_nan();
+ let bound_expr = expr.bind(schema, true);
+ assert!(bound_expr.is_err());
+ }
+
+ #[test]
+ fn test_bind_is_not_nan() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("qux").is_not_nan();
+ let bound_expr = expr.bind(schema, true).unwrap();
+ assert_eq!(&format!("{bound_expr}"), "qux IS NOT NAN");
+ }
+
+ #[test]
+ fn test_bind_is_not_nan_wrong_type() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("foo").is_not_nan();
+ let bound_expr = expr.bind(schema, true);
+ assert!(bound_expr.is_err());
+ }
+
#[test]
fn test_bind_less_than() {
let schema = table_schema_simple();
@@ -823,6 +861,38 @@ mod tests {
assert!(bound_expr.is_err());
}
+ #[test]
+ fn test_bind_less_than_or_eq() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("bar").less_than_or_equal_to(Datum::int(10));
+ let bound_expr = expr.bind(schema, true).unwrap();
+ assert_eq!(&format!("{bound_expr}"), "bar <= 10");
+ }
+
+ #[test]
+ fn test_bind_less_than_or_eq_wrong_type() {
+ let schema = table_schema_simple();
+ let expr =
Reference::new("bar").less_than_or_equal_to(Datum::string("abcd"));
+ let bound_expr = expr.bind(schema, true);
+ assert!(bound_expr.is_err());
+ }
+
+ #[test]
+ fn test_bind_greater_than() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("bar").greater_than(Datum::int(10));
+ let bound_expr = expr.bind(schema, true).unwrap();
+ assert_eq!(&format!("{bound_expr}"), "bar > 10");
+ }
+
+ #[test]
+ fn test_bind_greater_than_wrong_type() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("bar").greater_than(Datum::string("abcd"));
+ let bound_expr = expr.bind(schema, true);
+ assert!(bound_expr.is_err());
+ }
+
#[test]
fn test_bind_greater_than_or_eq() {
let schema = table_schema_simple();
@@ -839,6 +909,70 @@ mod tests {
assert!(bound_expr.is_err());
}
+ #[test]
+ fn test_bind_equal_to() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("bar").equal_to(Datum::int(10));
+ let bound_expr = expr.bind(schema, true).unwrap();
+ assert_eq!(&format!("{bound_expr}"), "bar = 10");
+ }
+
+ #[test]
+ fn test_bind_equal_to_wrong_type() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("bar").equal_to(Datum::string("abcd"));
+ let bound_expr = expr.bind(schema, true);
+ assert!(bound_expr.is_err());
+ }
+
+ #[test]
+ fn test_bind_not_equal_to() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("bar").not_equal_to(Datum::int(10));
+ let bound_expr = expr.bind(schema, true).unwrap();
+ assert_eq!(&format!("{bound_expr}"), "bar != 10");
+ }
+
+ #[test]
+ fn test_bind_not_equal_to_wrong_type() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("bar").not_equal_to(Datum::string("abcd"));
+ let bound_expr = expr.bind(schema, true);
+ assert!(bound_expr.is_err());
+ }
+
+ #[test]
+ fn test_bind_starts_with() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("foo").starts_with(Datum::string("abcd"));
+ let bound_expr = expr.bind(schema, true).unwrap();
+ assert_eq!(&format!("{bound_expr}"), r#"foo STARTS WITH "abcd""#);
+ }
+
+ #[test]
+ fn test_bind_starts_with_wrong_type() {
+ let schema = table_schema_simple();
+ let expr = Reference::new("bar").starts_with(Datum::string("abcd"));
+ let bound_expr = expr.bind(schema, true);
+ assert!(bound_expr.is_err());
+ }
+
+ #[test]
+ fn test_bind_not_starts_with() {
+ let schema = table_schema_simple();
+ let expr =
Reference::new("foo").not_starts_with(Datum::string("abcd"));
+ let bound_expr = expr.bind(schema, true).unwrap();
+ assert_eq!(&format!("{bound_expr}"), r#"foo NOT STARTS WITH "abcd""#);
+ }
+
+ #[test]
+ fn test_bind_not_starts_with_wrong_type() {
+ let schema = table_schema_simple();
+ let expr =
Reference::new("bar").not_starts_with(Datum::string("abcd"));
+ let bound_expr = expr.bind(schema, true);
+ assert!(bound_expr.is_err());
+ }
+
#[test]
fn test_bind_in() {
let schema = table_schema_simple();
diff --git a/crates/iceberg/src/expr/term.rs b/crates/iceberg/src/expr/term.rs
index 15cb298..94ae6bc 100644
--- a/crates/iceberg/src/expr/term.rs
+++ b/crates/iceberg/src/expr/term.rs
@@ -69,6 +69,46 @@ impl Reference {
))
}
+ /// Creates an less than or equal to expression. For example, `a <= 10`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ ///
+ /// use iceberg::expr::Reference;
+ /// use iceberg::spec::Datum;
+ /// let expr = Reference::new("a").less_than_or_equal_to(Datum::long(10));
+ ///
+ /// assert_eq!(&format!("{expr}"), "a <= 10");
+ /// ```
+ pub fn less_than_or_equal_to(self, datum: Datum) -> Predicate {
+ Predicate::Binary(BinaryExpression::new(
+ PredicateOperator::LessThanOrEq,
+ self,
+ datum,
+ ))
+ }
+
+ /// Creates an greater than expression. For example, `a > 10`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ ///
+ /// use iceberg::expr::Reference;
+ /// use iceberg::spec::Datum;
+ /// let expr = Reference::new("a").greater_than(Datum::long(10));
+ ///
+ /// assert_eq!(&format!("{expr}"), "a > 10");
+ /// ```
+ pub fn greater_than(self, datum: Datum) -> Predicate {
+ Predicate::Binary(BinaryExpression::new(
+ PredicateOperator::GreaterThan,
+ self,
+ datum,
+ ))
+ }
+
/// Creates a greater-than-or-equal-to than expression. For example, `a >=
10`.
///
/// # Example
@@ -89,6 +129,111 @@ impl Reference {
))
}
+ /// Creates an equal-to expression. For example, `a = 10`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ ///
+ /// use iceberg::expr::Reference;
+ /// use iceberg::spec::Datum;
+ /// let expr = Reference::new("a").equal_to(Datum::long(10));
+ ///
+ /// assert_eq!(&format!("{expr}"), "a = 10");
+ /// ```
+ pub fn equal_to(self, datum: Datum) -> Predicate {
+ Predicate::Binary(BinaryExpression::new(PredicateOperator::Eq, self,
datum))
+ }
+
+ /// Creates a not equal-to expression. For example, `a!= 10`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ ///
+ /// use iceberg::expr::Reference;
+ /// use iceberg::spec::Datum;
+ /// let expr = Reference::new("a").not_equal_to(Datum::long(10));
+ ///
+ /// assert_eq!(&format!("{expr}"), "a != 10");
+ /// ```
+ pub fn not_equal_to(self, datum: Datum) -> Predicate {
+ Predicate::Binary(BinaryExpression::new(PredicateOperator::NotEq,
self, datum))
+ }
+
+ /// Creates a start-with expression. For example, `a STARTS WITH "foo"`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ ///
+ /// use iceberg::expr::Reference;
+ /// use iceberg::spec::Datum;
+ /// let expr = Reference::new("a").starts_with(Datum::string("foo"));
+ ///
+ /// assert_eq!(&format!("{expr}"), r#"a STARTS WITH "foo""#);
+ /// ```
+ pub fn starts_with(self, datum: Datum) -> Predicate {
+ Predicate::Binary(BinaryExpression::new(
+ PredicateOperator::StartsWith,
+ self,
+ datum,
+ ))
+ }
+
+ /// Creates a not start-with expression. For example, `a NOT STARTS WITH
'foo'`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ ///
+ /// use iceberg::expr::Reference;
+ /// use iceberg::spec::Datum;
+ ///
+ /// let expr = Reference::new("a").not_starts_with(Datum::string("foo"));
+ ///
+ /// assert_eq!(&format!("{expr}"), r#"a NOT STARTS WITH "foo""#);
+ /// ```
+ pub fn not_starts_with(self, datum: Datum) -> Predicate {
+ Predicate::Binary(BinaryExpression::new(
+ PredicateOperator::NotStartsWith,
+ self,
+ datum,
+ ))
+ }
+
+ /// Creates an is-nan expression. For example, `a IS NAN`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ ///
+ /// use iceberg::expr::Reference;
+ /// use iceberg::spec::Datum;
+ /// let expr = Reference::new("a").is_nan();
+ ///
+ /// assert_eq!(&format!("{expr}"), "a IS NAN");
+ /// ```
+ pub fn is_nan(self) -> Predicate {
+ Predicate::Unary(UnaryExpression::new(PredicateOperator::IsNan, self))
+ }
+
+ /// Creates an is-not-nan expression. For example, `a IS NOT NAN`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ ///
+ /// use iceberg::expr::Reference;
+ /// use iceberg::spec::Datum;
+ /// let expr = Reference::new("a").is_not_nan();
+ ///
+ /// assert_eq!(&format!("{expr}"), "a IS NOT NAN");
+ /// ```
+ pub fn is_not_nan(self) -> Predicate {
+ Predicate::Unary(UnaryExpression::new(PredicateOperator::NotNan, self))
+ }
+
/// Creates an is-null expression. For example, `a IS NULL`.
///
/// # Example