Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-plan/src/plans/optimizer/simplify_expr/arity.rs
7889 views
1
use super::*;
2
use crate::dsl::Operator;
3
4
pub(super) fn simplify_binary(
5
left: Node,
6
op: Operator,
7
right: Node,
8
ctx: OptimizeExprContext,
9
expr_arena: &mut Arena<AExpr>,
10
) -> Option<AExpr> {
11
let in_filter = ctx.in_filter;
12
13
use Operator as O;
14
match op {
15
O::And => {
16
let left_ae = expr_arena.get(left);
17
let right_ae = expr_arena.get(right);
18
19
// true AND x => x
20
if matches!(
21
left_ae,
22
AExpr::Literal(lv) if lv.bool() == Some(true)
23
) && in_filter
24
{
25
// Only in filter as we might change the name from "literal"
26
// to whatever lhs columns is.
27
return Some(right_ae.clone());
28
}
29
30
// x AND true => x
31
if matches!(
32
right_ae,
33
AExpr::Literal(lv) if lv.bool() == Some(true)
34
) {
35
return Some(left_ae.clone());
36
}
37
38
// x AND false -> false
39
// FIXME: we need an optimizer redesign to allow x & false to be optimized
40
// in general as we can forget the length of a series otherwise.
41
// In filter we allow it as the length is not important there.
42
if (is_scalar_ae(left, expr_arena) | in_filter)
43
&& matches!(
44
right_ae,
45
AExpr::Literal(lv) if lv.bool() == Some(false)
46
)
47
{
48
return Some(AExpr::Literal(Scalar::from(false).into()));
49
}
50
},
51
O::Or => {
52
let left_ae = expr_arena.get(left);
53
let right_ae = expr_arena.get(right);
54
55
// false OR x => x
56
if matches!(
57
left_ae,
58
AExpr::Literal(lv) if lv.bool() == Some(false)
59
) && in_filter
60
{
61
// Only in filter as we might change the name from "literal"
62
// to whatever lhs columns is.
63
return Some(right_ae.clone());
64
}
65
66
// x OR false => x
67
if matches!(
68
right_ae,
69
AExpr::Literal(lv) if lv.bool() == Some(false)
70
) {
71
return Some(left_ae.clone());
72
}
73
// true OR x => true
74
// FIXME: we need an optimizer redesign to allow true | x to be optimized
75
// in general as we can forget the length of a series otherwise.
76
// In filter we allow it as the length is not important there.
77
if (is_scalar_ae(left, expr_arena) | in_filter)
78
&& matches!(
79
right_ae,
80
AExpr::Literal(lv) if lv.bool() == Some(true)
81
)
82
{
83
return Some(AExpr::Literal(Scalar::from(true).into()));
84
}
85
86
// x OR true => true
87
// FIXME: we need an optimizer redesign to allow true | x to be optimized
88
// in general as we can forget the length of a series otherwise.
89
// In filter we allow it as the length is not important there.
90
if matches!(
91
left_ae,
92
AExpr::Literal(lv) if lv.bool() == Some(true)
93
) && (is_scalar_ae(right, expr_arena) | in_filter)
94
{
95
return Some(AExpr::Literal(Scalar::from(true).into()));
96
}
97
},
98
99
_ => {},
100
}
101
None
102
}
103
104
pub(super) fn simplify_ternary(
105
predicate: Node,
106
truthy: Node,
107
falsy: Node,
108
expr_arena: &mut Arena<AExpr>,
109
) -> Option<AExpr> {
110
let predicate = expr_arena.get(predicate);
111
112
if let AExpr::Literal(lv) = predicate {
113
match lv.bool() {
114
None => {},
115
Some(true) => {
116
// Only replace if both are scalar or both are not scalar and are the same length,
117
// the latter is tested by checking if they are elementwise.
118
let t_is_scalar = is_scalar_ae(truthy, expr_arena);
119
let f_is_scalar = is_scalar_ae(falsy, expr_arena);
120
121
if t_is_scalar == f_is_scalar
122
&& is_elementwise_rec(truthy, expr_arena)
123
&& is_elementwise_rec(falsy, expr_arena)
124
{
125
return Some(expr_arena.get(truthy).clone());
126
}
127
},
128
Some(false) => {
129
let t_is_scalar = is_scalar_ae(truthy, expr_arena);
130
let f_is_scalar = is_scalar_ae(falsy, expr_arena);
131
132
if t_is_scalar == f_is_scalar
133
&& is_elementwise_rec(truthy, expr_arena)
134
&& is_elementwise_rec(falsy, expr_arena)
135
{
136
return Some(expr_arena.get(falsy).clone());
137
}
138
},
139
}
140
}
141
142
None
143
}
144
145