19
19
//! Predicate expressions are used to filter data, and evaluates to a boolean value. For example,
20
20
//! `a > 10` is a predicate expression, and it evaluates to `true` if `a` is greater than `10`,
21
21
22
- use crate :: expr:: { BoundReference , PredicateOperator , UnboundReference } ;
23
- use crate :: spec:: Literal ;
22
+ use crate :: expr:: { BoundReference , PredicateOperator , Reference } ;
23
+ use crate :: spec:: Datum ;
24
24
use std:: collections:: HashSet ;
25
+ use std:: fmt:: { Debug , Display , Formatter } ;
26
+ use std:: ops:: Not ;
25
27
26
28
/// Logical expression, such as `AND`, `OR`, `NOT`.
27
29
pub struct LogicalExpression < T , const N : usize > {
28
30
inputs : [ Box < T > ; N ] ,
29
31
}
30
32
33
+ impl < T : Debug , const N : usize > Debug for LogicalExpression < T , N > {
34
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
35
+ f. debug_struct ( "LogicalExpression" )
36
+ . field ( "inputs" , & self . inputs )
37
+ . finish ( )
38
+ }
39
+ }
40
+
41
+ impl < T , const N : usize > LogicalExpression < T , N > {
42
+ fn new ( inputs : [ Box < T > ; N ] ) -> Self {
43
+ Self { inputs }
44
+ }
45
+
46
+ /// Return inputs of this logical expression.
47
+ pub fn inputs ( & self ) -> [ & T ; N ] {
48
+ let mut ret: [ & T ; N ] = [ self . inputs [ 0 ] . as_ref ( ) ; N ] ;
49
+ for ( i, item) in ret. iter_mut ( ) . enumerate ( ) {
50
+ * item = & self . inputs [ i] ;
51
+ }
52
+ ret
53
+ }
54
+ }
55
+
31
56
/// Unary predicate, for example, `a IS NULL`.
32
57
pub struct UnaryExpression < T > {
33
58
/// Operator of this predicate, must be single operand operator.
@@ -36,14 +61,59 @@ pub struct UnaryExpression<T> {
36
61
term : T ,
37
62
}
38
63
64
+ impl < T : Debug > Debug for UnaryExpression < T > {
65
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
66
+ f. debug_struct ( "UnaryExpression" )
67
+ . field ( "op" , & self . op )
68
+ . field ( "term" , & self . term )
69
+ . finish ( )
70
+ }
71
+ }
72
+
73
+ impl < T : Display > Display for UnaryExpression < T > {
74
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
75
+ write ! ( f, "{} {}" , self . term, self . op)
76
+ }
77
+ }
78
+
79
+ impl < T > UnaryExpression < T > {
80
+ pub ( crate ) fn new ( op : PredicateOperator , term : T ) -> Self {
81
+ debug_assert ! ( op. is_unary( ) ) ;
82
+ Self { op, term }
83
+ }
84
+ }
85
+
39
86
/// Binary predicate, for example, `a > 10`.
40
87
pub struct BinaryExpression < T > {
41
88
/// Operator of this predicate, must be binary operator, such as `=`, `>`, `<`, etc.
42
89
op : PredicateOperator ,
43
90
/// Term of this predicate, for example, `a` in `a > 10`.
44
91
term : T ,
45
92
/// Literal of this predicate, for example, `10` in `a > 10`.
46
- literal : Literal ,
93
+ literal : Datum ,
94
+ }
95
+
96
+ impl < T : Debug > Debug for BinaryExpression < T > {
97
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
98
+ f. debug_struct ( "BinaryExpression" )
99
+ . field ( "op" , & self . op )
100
+ . field ( "term" , & self . term )
101
+ . field ( "literal" , & self . literal )
102
+ . finish ( )
103
+ }
104
+ }
105
+
106
+ impl < T > BinaryExpression < T > {
107
+ pub ( crate ) fn new ( op : PredicateOperator , term : T , literal : Datum ) -> Self {
108
+ debug_assert ! ( op. is_binary( ) ) ;
109
+ Self { op, term, literal }
110
+ }
111
+ }
112
+
113
+ impl < T : Display > Display for BinaryExpression < T > {
114
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
115
+ write ! ( f, "{} {} {}" , self . term, self . op, self . literal)
116
+ }
47
117
}
48
118
49
119
/// Set predicates, for example, `a in (1, 2, 3)`.
@@ -53,26 +123,139 @@ pub struct SetExpression<T> {
53
123
/// Term of this predicate, for example, `a` in `a in (1, 2, 3)`.
54
124
term : T ,
55
125
/// Literals of this predicate, for example, `(1, 2, 3)` in `a in (1, 2, 3)`.
56
- literals : HashSet < Literal > ,
126
+ literals : HashSet < Datum > ,
127
+ }
128
+
129
+ impl < T : Debug > Debug for SetExpression < T > {
130
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
131
+ f. debug_struct ( "SetExpression" )
132
+ . field ( "op" , & self . op )
133
+ . field ( "term" , & self . term )
134
+ . field ( "literal" , & self . literals )
135
+ . finish ( )
136
+ }
57
137
}
58
138
59
139
/// Unbound predicate expression before binding to a schema.
60
- pub enum UnboundPredicate {
140
+ #[ derive( Debug ) ]
141
+ pub enum Predicate {
61
142
/// And predicate, for example, `a > 10 AND b < 20`.
62
- And ( LogicalExpression < UnboundPredicate , 2 > ) ,
143
+ And ( LogicalExpression < Predicate , 2 > ) ,
63
144
/// Or predicate, for example, `a > 10 OR b < 20`.
64
- Or ( LogicalExpression < UnboundPredicate , 2 > ) ,
145
+ Or ( LogicalExpression < Predicate , 2 > ) ,
65
146
/// Not predicate, for example, `NOT (a > 10)`.
66
- Not ( LogicalExpression < UnboundPredicate , 1 > ) ,
147
+ Not ( LogicalExpression < Predicate , 1 > ) ,
67
148
/// Unary expression, for example, `a IS NULL`.
68
- Unary ( UnaryExpression < UnboundReference > ) ,
149
+ Unary ( UnaryExpression < Reference > ) ,
69
150
/// Binary expression, for example, `a > 10`.
70
- Binary ( BinaryExpression < UnboundReference > ) ,
151
+ Binary ( BinaryExpression < Reference > ) ,
71
152
/// Set predicates, for example, `a in (1, 2, 3)`.
72
- Set ( SetExpression < UnboundReference > ) ,
153
+ Set ( SetExpression < Reference > ) ,
154
+ }
155
+
156
+ impl Display for Predicate {
157
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
158
+ match self {
159
+ Predicate :: And ( expr) => {
160
+ write ! ( f, "({}) AND ({})" , expr. inputs( ) [ 0 ] , expr. inputs( ) [ 1 ] )
161
+ }
162
+ Predicate :: Or ( expr) => {
163
+ write ! ( f, "({}) OR ({})" , expr. inputs( ) [ 0 ] , expr. inputs( ) [ 1 ] )
164
+ }
165
+ Predicate :: Not ( expr) => {
166
+ write ! ( f, "NOT ({})" , expr. inputs( ) [ 0 ] )
167
+ }
168
+ Predicate :: Unary ( expr) => {
169
+ write ! ( f, "{}" , expr. term)
170
+ }
171
+ Predicate :: Binary ( expr) => {
172
+ write ! ( f, "{} {} {}" , expr. term, expr. op, expr. literal)
173
+ }
174
+ Predicate :: Set ( expr) => {
175
+ write ! (
176
+ f,
177
+ "{} {} ({})" ,
178
+ expr. term,
179
+ expr. op,
180
+ expr. literals
181
+ . iter( )
182
+ . map( |l| format!( "{:?}" , l) )
183
+ . collect:: <Vec <String >>( )
184
+ . join( ", " )
185
+ )
186
+ }
187
+ }
188
+ }
189
+ }
190
+
191
+ impl Predicate {
192
+ /// Combines two predicates with `AND`.
193
+ ///
194
+ /// # Example
195
+ ///
196
+ /// ```rust
197
+ /// use std::ops::Bound::Unbounded;
198
+ /// use iceberg::expr::BoundPredicate::Unary;
199
+ /// use iceberg::expr::Reference;
200
+ /// use iceberg::spec::Datum;
201
+ /// let expr1 = Reference::new("a").less_than(Datum::long(10));
202
+ ///
203
+ /// let expr2 = Reference::new("b").less_than(Datum::long(20));
204
+ ///
205
+ /// let expr = expr1.and(expr2);
206
+ ///
207
+ /// assert_eq!(&format!("{expr}"), "(a < 10) AND (b < 20)");
208
+ /// ```
209
+ pub fn and ( self , other : Predicate ) -> Predicate {
210
+ Predicate :: And ( LogicalExpression :: new ( [ Box :: new ( self ) , Box :: new ( other) ] ) )
211
+ }
212
+
213
+ /// Combines two predicates with `OR`.
214
+ ///
215
+ /// # Example
216
+ ///
217
+ /// ```rust
218
+ /// use std::ops::Bound::Unbounded;
219
+ /// use iceberg::expr::BoundPredicate::Unary;
220
+ /// use iceberg::expr::Reference;
221
+ /// use iceberg::spec::Datum;
222
+ /// let expr1 = Reference::new("a").less_than(Datum::long(10));
223
+ ///
224
+ /// let expr2 = Reference::new("b").less_than(Datum::long(20));
225
+ ///
226
+ /// let expr = expr1.or(expr2);
227
+ ///
228
+ /// assert_eq!(&format!("{expr}"), "(a < 10) OR (b < 20)");
229
+ /// ```
230
+ pub fn or ( self , other : Predicate ) -> Predicate {
231
+ Predicate :: Or ( LogicalExpression :: new ( [ Box :: new ( self ) , Box :: new ( other) ] ) )
232
+ }
233
+ }
234
+
235
+ impl Not for Predicate {
236
+ type Output = Predicate ;
237
+
238
+ /// Create a predicate which is the reverse of this predicate. For example: `NOT (a > 10)`
239
+ /// # Example
240
+ ///
241
+ ///```rust
242
+ ///use std::ops::Bound::Unbounded;
243
+ ///use iceberg::expr::BoundPredicate::Unary;
244
+ ///use iceberg::expr::Reference;
245
+ ///use iceberg::spec::Datum;
246
+ ///let expr1 = Reference::new("a").less_than(Datum::long(10));
247
+ ///
248
+ ///let expr = !expr1;
249
+ ///
250
+ ///assert_eq!(&format!("{expr}"), "NOT (a < 10)");
251
+ ///```
252
+ fn not ( self ) -> Self :: Output {
253
+ Predicate :: Not ( LogicalExpression :: new ( [ Box :: new ( self ) ] ) )
254
+ }
73
255
}
74
256
75
257
/// Bound predicate expression after binding to a schema.
258
+ #[ derive( Debug ) ]
76
259
pub enum BoundPredicate {
77
260
/// An expression always evaluates to true.
78
261
AlwaysTrue ,
0 commit comments