Skip to content

Commit c61e7e5

Browse files
authored
Simplify Between expression to Eq (#14994)
* simplify between equal case * cleanup
1 parent dd0fd88 commit c61e7e5

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,27 @@ impl<S: SimplifyInfo> TreeNodeRewriter for Simplifier<'_, S> {
942942
op: And,
943943
right,
944944
}) if is_op_with(Or, &left, &right) => Transformed::yes(*right),
945+
// A >= constant AND constant <= A --> A = constant
946+
Expr::BinaryExpr(BinaryExpr {
947+
left,
948+
op: And,
949+
right,
950+
}) if can_reduce_to_equal_statement(&left, &right) => {
951+
if let Expr::BinaryExpr(BinaryExpr {
952+
left: left_left,
953+
right: left_right,
954+
..
955+
}) = *left
956+
{
957+
Transformed::yes(Expr::BinaryExpr(BinaryExpr {
958+
left: left_left,
959+
op: Eq,
960+
right: left_right,
961+
}))
962+
} else {
963+
return internal_err!("can_reduce_to_equal_statement should only be called with a BinaryExpr");
964+
}
965+
}
945966

946967
//
947968
// Rules for Multiply

datafusion/optimizer/src/simplify_expressions/utils.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,25 @@ pub fn is_op_with(target_op: Operator, haystack: &Expr, needle: &Expr) -> bool {
214214
matches!(haystack, Expr::BinaryExpr(BinaryExpr { left, op, right }) if op == &target_op && (needle == left.as_ref() || needle == right.as_ref()) && !needle.is_volatile())
215215
}
216216

217+
pub fn can_reduce_to_equal_statement(haystack: &Expr, needle: &Expr) -> bool {
218+
match (haystack, needle) {
219+
// a >= constant and constant <= a => a = constant
220+
(
221+
Expr::BinaryExpr(BinaryExpr {
222+
left,
223+
op: Operator::GtEq,
224+
right,
225+
}),
226+
Expr::BinaryExpr(BinaryExpr {
227+
left: n_left,
228+
op: Operator::LtEq,
229+
right: n_right,
230+
}),
231+
) if left == n_left && right == n_right => true,
232+
_ => false,
233+
}
234+
}
235+
217236
/// returns true if `not_expr` is !`expr` (not)
218237
pub fn is_not_of(not_expr: &Expr, expr: &Expr) -> bool {
219238
matches!(not_expr, Expr::Not(inner) if expr == inner.as_ref())
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
statement count 0
19+
create table t(a int) as values (1);
20+
21+
# test between simplification
22+
query TT
23+
explain select a from t where a BETWEEN 3 and 3
24+
----
25+
logical_plan
26+
01)Filter: t.a = Int32(3)
27+
02)--TableScan: t projection=[a]
28+
physical_plan
29+
01)CoalesceBatchesExec: target_batch_size=8192
30+
02)--FilterExec: a@0 = 3
31+
03)----DataSourceExec: partitions=1, partition_sizes=[1]
32+
33+
statement count 0
34+
drop table t;

0 commit comments

Comments
 (0)