datafusion_expr/
operation.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 implementations of operations (unary, binary etc.) for DataFusion expressions.
19
20use crate::expr::{Exists, Expr, InList, InSubquery, Like};
21use crate::expr_fn::binary_expr;
22use datafusion_expr_common::operator::Operator;
23use std::ops::{self, Not};
24
25/// Support `<expr> + <expr>` fluent style
26impl ops::Add for Expr {
27    type Output = Self;
28
29    fn add(self, rhs: Self) -> Self {
30        binary_expr(self, Operator::Plus, rhs)
31    }
32}
33
34/// Support `<expr> - <expr>` fluent style
35impl ops::Sub for Expr {
36    type Output = Self;
37
38    fn sub(self, rhs: Self) -> Self {
39        binary_expr(self, Operator::Minus, rhs)
40    }
41}
42
43/// Support `<expr> * <expr>` fluent style
44impl ops::Mul for Expr {
45    type Output = Self;
46
47    fn mul(self, rhs: Self) -> Self {
48        binary_expr(self, Operator::Multiply, rhs)
49    }
50}
51
52/// Support `<expr> / <expr>` fluent style
53impl ops::Div for Expr {
54    type Output = Self;
55
56    fn div(self, rhs: Self) -> Self {
57        binary_expr(self, Operator::Divide, rhs)
58    }
59}
60
61/// Support `<expr> % <expr>` fluent style
62impl ops::Rem for Expr {
63    type Output = Self;
64
65    fn rem(self, rhs: Self) -> Self {
66        binary_expr(self, Operator::Modulo, rhs)
67    }
68}
69
70/// Support `<expr> & <expr>` fluent style
71impl ops::BitAnd for Expr {
72    type Output = Self;
73
74    fn bitand(self, rhs: Self) -> Self {
75        binary_expr(self, Operator::BitwiseAnd, rhs)
76    }
77}
78
79/// Support `<expr> | <expr>` fluent style
80impl ops::BitOr for Expr {
81    type Output = Self;
82
83    fn bitor(self, rhs: Self) -> Self {
84        binary_expr(self, Operator::BitwiseOr, rhs)
85    }
86}
87
88/// Support `<expr> ^ <expr>` fluent style
89impl ops::BitXor for Expr {
90    type Output = Self;
91
92    fn bitxor(self, rhs: Self) -> Self {
93        binary_expr(self, Operator::BitwiseXor, rhs)
94    }
95}
96
97/// Support `<expr> << <expr>` fluent style
98impl ops::Shl for Expr {
99    type Output = Self;
100
101    fn shl(self, rhs: Self) -> Self::Output {
102        binary_expr(self, Operator::BitwiseShiftLeft, rhs)
103    }
104}
105
106/// Support `<expr> >> <expr>` fluent style
107impl ops::Shr for Expr {
108    type Output = Self;
109
110    fn shr(self, rhs: Self) -> Self::Output {
111        binary_expr(self, Operator::BitwiseShiftRight, rhs)
112    }
113}
114
115/// Support `- <expr>` fluent style
116impl ops::Neg for Expr {
117    type Output = Self;
118
119    fn neg(self) -> Self::Output {
120        Expr::Negative(Box::new(self))
121    }
122}
123
124/// Support `NOT <expr>` fluent style
125impl Not for Expr {
126    type Output = Self;
127
128    fn not(self) -> Self::Output {
129        match self {
130            Expr::Like(Like {
131                negated,
132                expr,
133                pattern,
134                escape_char,
135                case_insensitive,
136            }) => Expr::Like(Like::new(
137                !negated,
138                expr,
139                pattern,
140                escape_char,
141                case_insensitive,
142            )),
143            Expr::SimilarTo(Like {
144                negated,
145                expr,
146                pattern,
147                escape_char,
148                case_insensitive,
149            }) => Expr::SimilarTo(Like::new(
150                !negated,
151                expr,
152                pattern,
153                escape_char,
154                case_insensitive,
155            )),
156            Expr::InList(InList {
157                expr,
158                list,
159                negated,
160            }) => Expr::InList(InList::new(expr, list, !negated)),
161            Expr::Exists(Exists { subquery, negated }) => {
162                Expr::Exists(Exists::new(subquery, !negated))
163            }
164            Expr::InSubquery(InSubquery {
165                expr,
166                subquery,
167                negated,
168            }) => Expr::InSubquery(InSubquery::new(expr, subquery, !negated)),
169            _ => Expr::Not(Box::new(self)),
170        }
171    }
172}
173
174#[cfg(test)]
175mod tests {
176    use crate::lit;
177
178    #[test]
179    fn test_operators() {
180        // Add
181        assert_eq!(
182            format!("{}", lit(1u32) + lit(2u32)),
183            "UInt32(1) + UInt32(2)"
184        );
185        // Sub
186        assert_eq!(
187            format!("{}", lit(1u32) - lit(2u32)),
188            "UInt32(1) - UInt32(2)"
189        );
190        // Mul
191        assert_eq!(
192            format!("{}", lit(1u32) * lit(2u32)),
193            "UInt32(1) * UInt32(2)"
194        );
195        // Div
196        assert_eq!(
197            format!("{}", lit(1u32) / lit(2u32)),
198            "UInt32(1) / UInt32(2)"
199        );
200        // Rem
201        assert_eq!(
202            format!("{}", lit(1u32) % lit(2u32)),
203            "UInt32(1) % UInt32(2)"
204        );
205        // BitAnd
206        assert_eq!(
207            format!("{}", lit(1u32) & lit(2u32)),
208            "UInt32(1) & UInt32(2)"
209        );
210        // BitOr
211        assert_eq!(
212            format!("{}", lit(1u32) | lit(2u32)),
213            "UInt32(1) | UInt32(2)"
214        );
215        // BitXor
216        assert_eq!(
217            format!("{}", lit(1u32) ^ lit(2u32)),
218            "UInt32(1) BIT_XOR UInt32(2)"
219        );
220        // Shl
221        assert_eq!(
222            format!("{}", lit(1u32) << lit(2u32)),
223            "UInt32(1) << UInt32(2)"
224        );
225        // Shr
226        assert_eq!(
227            format!("{}", lit(1u32) >> lit(2u32)),
228            "UInt32(1) >> UInt32(2)"
229        );
230        // Neg
231        assert_eq!(format!("{}", -lit(1u32)), "(- UInt32(1))");
232        // Not
233        assert_eq!(format!("{}", !lit(1u32)), "NOT UInt32(1)");
234    }
235}