/Users/andrewlamb/Software/datafusion/datafusion/expr-common/src/operator.rs
Line | Count | Source (jump to first uncovered line) |
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 | | use std::fmt; |
19 | | |
20 | | /// Operators applied to expressions |
21 | | #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Hash)] |
22 | | pub enum Operator { |
23 | | /// Expressions are equal |
24 | | Eq, |
25 | | /// Expressions are not equal |
26 | | NotEq, |
27 | | /// Left side is smaller than right side |
28 | | Lt, |
29 | | /// Left side is smaller or equal to right side |
30 | | LtEq, |
31 | | /// Left side is greater than right side |
32 | | Gt, |
33 | | /// Left side is greater or equal to right side |
34 | | GtEq, |
35 | | /// Addition |
36 | | Plus, |
37 | | /// Subtraction |
38 | | Minus, |
39 | | /// Multiplication operator, like `*` |
40 | | Multiply, |
41 | | /// Division operator, like `/` |
42 | | Divide, |
43 | | /// Remainder operator, like `%` |
44 | | Modulo, |
45 | | /// Logical AND, like `&&` |
46 | | And, |
47 | | /// Logical OR, like `||` |
48 | | Or, |
49 | | /// `IS DISTINCT FROM` (see [`distinct`]) |
50 | | /// |
51 | | /// [`distinct`]: arrow::compute::kernels::cmp::distinct |
52 | | IsDistinctFrom, |
53 | | /// `IS NOT DISTINCT FROM` (see [`not_distinct`]) |
54 | | /// |
55 | | /// [`not_distinct`]: arrow::compute::kernels::cmp::not_distinct |
56 | | IsNotDistinctFrom, |
57 | | /// Case sensitive regex match |
58 | | RegexMatch, |
59 | | /// Case insensitive regex match |
60 | | RegexIMatch, |
61 | | /// Case sensitive regex not match |
62 | | RegexNotMatch, |
63 | | /// Case insensitive regex not match |
64 | | RegexNotIMatch, |
65 | | /// Case sensitive pattern match |
66 | | LikeMatch, |
67 | | /// Case insensitive pattern match |
68 | | ILikeMatch, |
69 | | /// Case sensitive pattern not match |
70 | | NotLikeMatch, |
71 | | /// Case insensitive pattern not match |
72 | | NotILikeMatch, |
73 | | /// Bitwise and, like `&` |
74 | | BitwiseAnd, |
75 | | /// Bitwise or, like `|` |
76 | | BitwiseOr, |
77 | | /// Bitwise xor, such as `^` in MySQL or `#` in PostgreSQL |
78 | | BitwiseXor, |
79 | | /// Bitwise right, like `>>` |
80 | | BitwiseShiftRight, |
81 | | /// Bitwise left, like `<<` |
82 | | BitwiseShiftLeft, |
83 | | /// String concat |
84 | | StringConcat, |
85 | | /// At arrow, like `@>` |
86 | | AtArrow, |
87 | | /// Arrow at, like `<@` |
88 | | ArrowAt, |
89 | | } |
90 | | |
91 | | impl Operator { |
92 | | /// If the operator can be negated, return the negated operator |
93 | | /// otherwise return None |
94 | 0 | pub fn negate(&self) -> Option<Operator> { |
95 | 0 | match self { |
96 | 0 | Operator::Eq => Some(Operator::NotEq), |
97 | 0 | Operator::NotEq => Some(Operator::Eq), |
98 | 0 | Operator::Lt => Some(Operator::GtEq), |
99 | 0 | Operator::LtEq => Some(Operator::Gt), |
100 | 0 | Operator::Gt => Some(Operator::LtEq), |
101 | 0 | Operator::GtEq => Some(Operator::Lt), |
102 | 0 | Operator::IsDistinctFrom => Some(Operator::IsNotDistinctFrom), |
103 | 0 | Operator::IsNotDistinctFrom => Some(Operator::IsDistinctFrom), |
104 | 0 | Operator::LikeMatch => Some(Operator::NotLikeMatch), |
105 | 0 | Operator::ILikeMatch => Some(Operator::NotILikeMatch), |
106 | 0 | Operator::NotLikeMatch => Some(Operator::LikeMatch), |
107 | 0 | Operator::NotILikeMatch => Some(Operator::ILikeMatch), |
108 | | Operator::Plus |
109 | | | Operator::Minus |
110 | | | Operator::Multiply |
111 | | | Operator::Divide |
112 | | | Operator::Modulo |
113 | | | Operator::And |
114 | | | Operator::Or |
115 | | | Operator::RegexMatch |
116 | | | Operator::RegexIMatch |
117 | | | Operator::RegexNotMatch |
118 | | | Operator::RegexNotIMatch |
119 | | | Operator::BitwiseAnd |
120 | | | Operator::BitwiseOr |
121 | | | Operator::BitwiseXor |
122 | | | Operator::BitwiseShiftRight |
123 | | | Operator::BitwiseShiftLeft |
124 | | | Operator::StringConcat |
125 | | | Operator::AtArrow |
126 | 0 | | Operator::ArrowAt => None, |
127 | | } |
128 | 0 | } |
129 | | |
130 | | /// Return true if the operator is a numerical operator. |
131 | | /// |
132 | | /// For example, 'Binary(a, +, b)' would be a numerical expression. |
133 | | /// PostgresSQL concept: <https://www.postgresql.org/docs/7.0/operators2198.htm> |
134 | 0 | pub fn is_numerical_operators(&self) -> bool { |
135 | 0 | matches!( |
136 | 0 | self, |
137 | | Operator::Plus |
138 | | | Operator::Minus |
139 | | | Operator::Multiply |
140 | | | Operator::Divide |
141 | | | Operator::Modulo |
142 | | ) |
143 | 0 | } |
144 | | |
145 | | /// Return true if the operator is a comparison operator. |
146 | | /// |
147 | | /// For example, 'Binary(a, >, b)' would be a comparison expression. |
148 | 33.6k | pub fn is_comparison_operator(&self) -> bool { |
149 | 22.1k | matches!( |
150 | 33.6k | self, |
151 | | Operator::Eq |
152 | | | Operator::NotEq |
153 | | | Operator::Lt |
154 | | | Operator::LtEq |
155 | | | Operator::Gt |
156 | | | Operator::GtEq |
157 | | | Operator::IsDistinctFrom |
158 | | | Operator::IsNotDistinctFrom |
159 | | | Operator::RegexMatch |
160 | | | Operator::RegexIMatch |
161 | | | Operator::RegexNotMatch |
162 | | | Operator::RegexNotIMatch |
163 | | ) |
164 | 33.6k | } |
165 | | |
166 | | /// Return true if the operator is a logic operator. |
167 | | /// |
168 | | /// For example, 'Binary(Binary(a, >, b), AND, Binary(a, <, b + 3))' would |
169 | | /// be a logical expression. |
170 | 0 | pub fn is_logic_operator(&self) -> bool { |
171 | 0 | matches!(self, Operator::And | Operator::Or) |
172 | 0 | } |
173 | | |
174 | | /// Return the operator where swapping lhs and rhs wouldn't change the result. |
175 | | /// |
176 | | /// For example `Binary(50, >=, a)` could also be represented as `Binary(a, <=, 50)`. |
177 | 0 | pub fn swap(&self) -> Option<Operator> { |
178 | 0 | match self { |
179 | 0 | Operator::Eq => Some(Operator::Eq), |
180 | 0 | Operator::NotEq => Some(Operator::NotEq), |
181 | 0 | Operator::Lt => Some(Operator::Gt), |
182 | 0 | Operator::LtEq => Some(Operator::GtEq), |
183 | 0 | Operator::Gt => Some(Operator::Lt), |
184 | 0 | Operator::GtEq => Some(Operator::LtEq), |
185 | 0 | Operator::AtArrow => Some(Operator::ArrowAt), |
186 | 0 | Operator::ArrowAt => Some(Operator::AtArrow), |
187 | | Operator::IsDistinctFrom |
188 | | | Operator::IsNotDistinctFrom |
189 | | | Operator::Plus |
190 | | | Operator::Minus |
191 | | | Operator::Multiply |
192 | | | Operator::Divide |
193 | | | Operator::Modulo |
194 | | | Operator::And |
195 | | | Operator::Or |
196 | | | Operator::RegexMatch |
197 | | | Operator::RegexIMatch |
198 | | | Operator::RegexNotMatch |
199 | | | Operator::RegexNotIMatch |
200 | | | Operator::LikeMatch |
201 | | | Operator::ILikeMatch |
202 | | | Operator::NotLikeMatch |
203 | | | Operator::NotILikeMatch |
204 | | | Operator::BitwiseAnd |
205 | | | Operator::BitwiseOr |
206 | | | Operator::BitwiseXor |
207 | | | Operator::BitwiseShiftRight |
208 | | | Operator::BitwiseShiftLeft |
209 | 0 | | Operator::StringConcat => None, |
210 | | } |
211 | 0 | } |
212 | | |
213 | | /// Get the operator precedence |
214 | | /// use <https://www.postgresql.org/docs/7.2/sql-precedence.html> as a reference |
215 | 0 | pub fn precedence(&self) -> u8 { |
216 | 0 | match self { |
217 | 0 | Operator::Or => 5, |
218 | 0 | Operator::And => 10, |
219 | 0 | Operator::Eq | Operator::NotEq | Operator::LtEq | Operator::GtEq => 15, |
220 | 0 | Operator::Lt | Operator::Gt => 20, |
221 | | Operator::LikeMatch |
222 | | | Operator::NotLikeMatch |
223 | | | Operator::ILikeMatch |
224 | 0 | | Operator::NotILikeMatch => 25, |
225 | | Operator::IsDistinctFrom |
226 | | | Operator::IsNotDistinctFrom |
227 | | | Operator::RegexMatch |
228 | | | Operator::RegexNotMatch |
229 | | | Operator::RegexIMatch |
230 | | | Operator::RegexNotIMatch |
231 | | | Operator::BitwiseAnd |
232 | | | Operator::BitwiseOr |
233 | | | Operator::BitwiseShiftLeft |
234 | | | Operator::BitwiseShiftRight |
235 | | | Operator::BitwiseXor |
236 | | | Operator::StringConcat |
237 | | | Operator::AtArrow |
238 | 0 | | Operator::ArrowAt => 30, |
239 | 0 | Operator::Plus | Operator::Minus => 40, |
240 | 0 | Operator::Multiply | Operator::Divide | Operator::Modulo => 45, |
241 | | } |
242 | 0 | } |
243 | | } |
244 | | |
245 | | impl fmt::Display for Operator { |
246 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
247 | 0 | let display = match &self { |
248 | 0 | Operator::Eq => "=", |
249 | 0 | Operator::NotEq => "!=", |
250 | 0 | Operator::Lt => "<", |
251 | 0 | Operator::LtEq => "<=", |
252 | 0 | Operator::Gt => ">", |
253 | 0 | Operator::GtEq => ">=", |
254 | 0 | Operator::Plus => "+", |
255 | 0 | Operator::Minus => "-", |
256 | 0 | Operator::Multiply => "*", |
257 | 0 | Operator::Divide => "/", |
258 | 0 | Operator::Modulo => "%", |
259 | 0 | Operator::And => "AND", |
260 | 0 | Operator::Or => "OR", |
261 | 0 | Operator::RegexMatch => "~", |
262 | 0 | Operator::RegexIMatch => "~*", |
263 | 0 | Operator::RegexNotMatch => "!~", |
264 | 0 | Operator::RegexNotIMatch => "!~*", |
265 | 0 | Operator::LikeMatch => "~~", |
266 | 0 | Operator::ILikeMatch => "~~*", |
267 | 0 | Operator::NotLikeMatch => "!~~", |
268 | 0 | Operator::NotILikeMatch => "!~~*", |
269 | 0 | Operator::IsDistinctFrom => "IS DISTINCT FROM", |
270 | 0 | Operator::IsNotDistinctFrom => "IS NOT DISTINCT FROM", |
271 | 0 | Operator::BitwiseAnd => "&", |
272 | 0 | Operator::BitwiseOr => "|", |
273 | 0 | Operator::BitwiseXor => "BIT_XOR", |
274 | 0 | Operator::BitwiseShiftRight => ">>", |
275 | 0 | Operator::BitwiseShiftLeft => "<<", |
276 | 0 | Operator::StringConcat => "||", |
277 | 0 | Operator::AtArrow => "@>", |
278 | 0 | Operator::ArrowAt => "<@", |
279 | | }; |
280 | 0 | write!(f, "{display}") |
281 | 0 | } |
282 | | } |