iceberg/expr/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! This module contains expressions.
19
20mod term;
21use serde::{Deserialize, Serialize};
22pub use term::*;
23pub(crate) mod accessor;
24mod predicate;
25pub(crate) mod visitors;
26use std::fmt::{Display, Formatter};
27
28pub use predicate::*;
29
30use crate::spec::SchemaRef;
31
32/// Predicate operators used in expressions.
33///
34/// The discriminant of this enum is used for determining the type of the operator, see
35/// [`PredicateOperator::is_unary`], [`PredicateOperator::is_binary`], [`PredicateOperator::is_set`]
36#[allow(missing_docs)]
37#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
38#[non_exhaustive]
39#[repr(u16)]
40pub enum PredicateOperator {
41    // Unary operators
42    IsNull = 101,
43    NotNull = 102,
44    IsNan = 103,
45    NotNan = 104,
46
47    // Binary operators
48    LessThan = 201,
49    LessThanOrEq = 202,
50    GreaterThan = 203,
51    GreaterThanOrEq = 204,
52    Eq = 205,
53    NotEq = 206,
54    StartsWith = 207,
55    NotStartsWith = 208,
56
57    // Set operators
58    In = 301,
59    NotIn = 302,
60}
61
62impl Display for PredicateOperator {
63    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
64        match self {
65            PredicateOperator::IsNull => write!(f, "IS NULL"),
66            PredicateOperator::NotNull => write!(f, "IS NOT NULL"),
67            PredicateOperator::IsNan => write!(f, "IS NAN"),
68            PredicateOperator::NotNan => write!(f, "IS NOT NAN"),
69            PredicateOperator::LessThan => write!(f, "<"),
70            PredicateOperator::LessThanOrEq => write!(f, "<="),
71            PredicateOperator::GreaterThan => write!(f, ">"),
72            PredicateOperator::GreaterThanOrEq => write!(f, ">="),
73            PredicateOperator::Eq => write!(f, "="),
74            PredicateOperator::NotEq => write!(f, "!="),
75            PredicateOperator::In => write!(f, "IN"),
76            PredicateOperator::NotIn => write!(f, "NOT IN"),
77            PredicateOperator::StartsWith => write!(f, "STARTS WITH"),
78            PredicateOperator::NotStartsWith => write!(f, "NOT STARTS WITH"),
79        }
80    }
81}
82
83impl PredicateOperator {
84    /// Check if this operator is unary operator.
85    ///
86    /// # Example
87    ///
88    /// ```rust
89    /// use iceberg::expr::PredicateOperator;
90    /// assert!(PredicateOperator::IsNull.is_unary());
91    /// ```
92    pub fn is_unary(self) -> bool {
93        (self as u16) < (PredicateOperator::LessThan as u16)
94    }
95
96    /// Check if this operator is binary operator.
97    ///
98    /// # Example
99    ///
100    /// ```rust
101    /// use iceberg::expr::PredicateOperator;
102    /// assert!(PredicateOperator::LessThan.is_binary());
103    /// ```
104    pub fn is_binary(self) -> bool {
105        ((self as u16) > (PredicateOperator::NotNan as u16))
106            && ((self as u16) < (PredicateOperator::In as u16))
107    }
108
109    /// Check if this operator is set operator.
110    ///
111    /// # Example
112    ///
113    /// ```rust
114    /// use iceberg::expr::PredicateOperator;
115    /// assert!(PredicateOperator::In.is_set());
116    /// ```
117    pub fn is_set(self) -> bool {
118        (self as u16) > (PredicateOperator::NotStartsWith as u16)
119    }
120
121    /// Returns the predicate that is the inverse of self
122    ///
123    /// # Example
124    ///
125    /// ```rust
126    /// use iceberg::expr::PredicateOperator;
127    /// assert_eq!(
128    ///     PredicateOperator::IsNull.negate(),
129    ///     PredicateOperator::NotNull
130    /// );
131    /// assert_eq!(PredicateOperator::IsNan.negate(), PredicateOperator::NotNan);
132    /// assert_eq!(
133    ///     PredicateOperator::LessThan.negate(),
134    ///     PredicateOperator::GreaterThanOrEq
135    /// );
136    /// assert_eq!(
137    ///     PredicateOperator::GreaterThan.negate(),
138    ///     PredicateOperator::LessThanOrEq
139    /// );
140    /// assert_eq!(PredicateOperator::Eq.negate(), PredicateOperator::NotEq);
141    /// assert_eq!(PredicateOperator::In.negate(), PredicateOperator::NotIn);
142    /// assert_eq!(
143    ///     PredicateOperator::StartsWith.negate(),
144    ///     PredicateOperator::NotStartsWith
145    /// );
146    /// ```
147    pub fn negate(self) -> PredicateOperator {
148        match self {
149            PredicateOperator::IsNull => PredicateOperator::NotNull,
150            PredicateOperator::NotNull => PredicateOperator::IsNull,
151            PredicateOperator::IsNan => PredicateOperator::NotNan,
152            PredicateOperator::NotNan => PredicateOperator::IsNan,
153            PredicateOperator::LessThan => PredicateOperator::GreaterThanOrEq,
154            PredicateOperator::LessThanOrEq => PredicateOperator::GreaterThan,
155            PredicateOperator::GreaterThan => PredicateOperator::LessThanOrEq,
156            PredicateOperator::GreaterThanOrEq => PredicateOperator::LessThan,
157            PredicateOperator::Eq => PredicateOperator::NotEq,
158            PredicateOperator::NotEq => PredicateOperator::Eq,
159            PredicateOperator::In => PredicateOperator::NotIn,
160            PredicateOperator::NotIn => PredicateOperator::In,
161            PredicateOperator::StartsWith => PredicateOperator::NotStartsWith,
162            PredicateOperator::NotStartsWith => PredicateOperator::StartsWith,
163        }
164    }
165}
166
167/// Bind expression to a schema.
168pub trait Bind {
169    /// The type of the bound result.
170    type Bound;
171    /// Bind an expression to a schema.
172    fn bind(&self, schema: SchemaRef, case_sensitive: bool) -> crate::Result<Self::Bound>;
173}
174
175#[cfg(test)]
176mod tests {
177    use crate::expr::PredicateOperator;
178
179    #[test]
180    fn test_unary() {
181        assert!(PredicateOperator::IsNull.is_unary());
182        assert!(PredicateOperator::NotNull.is_unary());
183        assert!(PredicateOperator::IsNan.is_unary());
184        assert!(PredicateOperator::NotNan.is_unary());
185    }
186
187    #[test]
188    fn test_binary() {
189        assert!(PredicateOperator::LessThan.is_binary());
190        assert!(PredicateOperator::LessThanOrEq.is_binary());
191        assert!(PredicateOperator::GreaterThan.is_binary());
192        assert!(PredicateOperator::GreaterThanOrEq.is_binary());
193        assert!(PredicateOperator::Eq.is_binary());
194        assert!(PredicateOperator::NotEq.is_binary());
195        assert!(PredicateOperator::StartsWith.is_binary());
196        assert!(PredicateOperator::NotStartsWith.is_binary());
197    }
198
199    #[test]
200    fn test_set() {
201        assert!(PredicateOperator::In.is_set());
202        assert!(PredicateOperator::NotIn.is_set());
203    }
204}