Skip to content

Commit 60e5003

Browse files
rohitrastogiRohit Rastogi
and
Rohit Rastogi
authored
Stop copying LogicalPlan and Exprs in RewriteDisjunctivePredicate (#10305)
* Implement rewrite for RewriteDisjunctivePredicate * Eliminate more predicate/expr clones --------- Co-authored-by: Rohit Rastogi <[email protected]>
1 parent d3237b2 commit 60e5003

File tree

1 file changed

+62
-52
lines changed

1 file changed

+62
-52
lines changed

datafusion/optimizer/src/rewrite_disjunctive_predicate.rs

Lines changed: 62 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
2020
use crate::optimizer::ApplyOrder;
2121
use crate::{OptimizerConfig, OptimizerRule};
22+
use datafusion_common::internal_err;
23+
use datafusion_common::tree_node::Transformed;
2224
use datafusion_common::Result;
2325
use datafusion_expr::expr::BinaryExpr;
2426
use datafusion_expr::logical_plan::Filter;
@@ -56,29 +58,34 @@ use datafusion_expr::{Expr, LogicalPlan, Operator};
5658
///
5759
/// ```sql
5860
/// where
59-
/// p_partkey = l_partkey
60-
/// and l_shipmode in (‘AIR’, ‘AIR REG’)
61-
/// and l_shipinstruct = ‘DELIVER IN PERSON’
62-
/// and (
6361
/// (
62+
/// p_partkey = l_partkey
6463
/// and p_brand = ‘[BRAND1]’
6564
/// and p_container in ( ‘SM CASE’, ‘SM BOX’, ‘SM PACK’, ‘SM PKG’)
6665
/// and l_quantity >= [QUANTITY1] and l_quantity <= [QUANTITY1] + 10
6766
/// and p_size between 1 and 5
67+
/// and l_shipmode in (‘AIR’, ‘AIR REG’)
68+
/// and l_shipinstruct = ‘DELIVER IN PERSON’
6869
/// )
6970
/// or
7071
/// (
72+
/// p_partkey = l_partkey
7173
/// and p_brand = ‘[BRAND2]’
7274
/// and p_container in (‘MED BAG’, ‘MED BOX’, ‘MED PKG’, ‘MED PACK’)
7375
/// and l_quantity >= [QUANTITY2] and l_quantity <= [QUANTITY2] + 10
7476
/// and p_size between 1 and 10
77+
/// and l_shipmode in (‘AIR’, ‘AIR REG’)
78+
/// and l_shipinstruct = ‘DELIVER IN PERSON’
7579
/// )
7680
/// or
7781
/// (
82+
/// p_partkey = l_partkey
7883
/// and p_brand = ‘[BRAND3]’
7984
/// and p_container in ( ‘LG CASE’, ‘LG BOX’, ‘LG PACK’, ‘LG PKG’)
8085
/// and l_quantity >= [QUANTITY3] and l_quantity <= [QUANTITY3] + 10
8186
/// and p_size between 1 and 15
87+
/// and l_shipmode in (‘AIR’, ‘AIR REG’)
88+
/// and l_shipinstruct = ‘DELIVER IN PERSON’
8289
/// )
8390
/// )
8491
/// ```
@@ -128,21 +135,10 @@ impl RewriteDisjunctivePredicate {
128135
impl OptimizerRule for RewriteDisjunctivePredicate {
129136
fn try_optimize(
130137
&self,
131-
plan: &LogicalPlan,
138+
_plan: &LogicalPlan,
132139
_config: &dyn OptimizerConfig,
133140
) -> Result<Option<LogicalPlan>> {
134-
match plan {
135-
LogicalPlan::Filter(filter) => {
136-
let predicate = predicate(&filter.predicate)?;
137-
let rewritten_predicate = rewrite_predicate(predicate);
138-
let rewritten_expr = normalize_predicate(rewritten_predicate);
139-
Ok(Some(LogicalPlan::Filter(Filter::try_new(
140-
rewritten_expr,
141-
filter.input.clone(),
142-
)?)))
143-
}
144-
_ => Ok(None),
145-
}
141+
internal_err!("Should have called RewriteDisjunctivePredicate::rewrite")
146142
}
147143

148144
fn name(&self) -> &str {
@@ -152,6 +148,29 @@ impl OptimizerRule for RewriteDisjunctivePredicate {
152148
fn apply_order(&self) -> Option<ApplyOrder> {
153149
Some(ApplyOrder::TopDown)
154150
}
151+
152+
fn supports_rewrite(&self) -> bool {
153+
true
154+
}
155+
156+
fn rewrite(
157+
&self,
158+
plan: LogicalPlan,
159+
_config: &dyn OptimizerConfig,
160+
) -> Result<Transformed<LogicalPlan>> {
161+
match plan {
162+
LogicalPlan::Filter(filter) => {
163+
let predicate = predicate(filter.predicate)?;
164+
let rewritten_predicate = rewrite_predicate(predicate);
165+
let rewritten_expr = normalize_predicate(rewritten_predicate);
166+
Ok(Transformed::yes(LogicalPlan::Filter(Filter::try_new(
167+
rewritten_expr,
168+
filter.input,
169+
)?)))
170+
}
171+
_ => Ok(Transformed::no(plan)),
172+
}
173+
}
155174
}
156175

157176
#[derive(Clone, PartialEq, Debug)]
@@ -161,27 +180,23 @@ enum Predicate {
161180
Other { expr: Box<Expr> },
162181
}
163182

164-
fn predicate(expr: &Expr) -> Result<Predicate> {
183+
fn predicate(expr: Expr) -> Result<Predicate> {
165184
match expr {
166185
Expr::BinaryExpr(BinaryExpr { left, op, right }) => match op {
167186
Operator::And => {
168-
let args = vec![predicate(left)?, predicate(right)?];
187+
let args = vec![predicate(*left)?, predicate(*right)?];
169188
Ok(Predicate::And { args })
170189
}
171190
Operator::Or => {
172-
let args = vec![predicate(left)?, predicate(right)?];
191+
let args = vec![predicate(*left)?, predicate(*right)?];
173192
Ok(Predicate::Or { args })
174193
}
175194
_ => Ok(Predicate::Other {
176-
expr: Box::new(Expr::BinaryExpr(BinaryExpr::new(
177-
left.clone(),
178-
*op,
179-
right.clone(),
180-
))),
195+
expr: Box::new(Expr::BinaryExpr(BinaryExpr::new(left, op, right))),
181196
}),
182197
},
183198
_ => Ok(Predicate::Other {
184-
expr: Box::new(expr.clone()),
199+
expr: Box::new(expr),
185200
}),
186201
}
187202
}
@@ -210,8 +225,8 @@ fn rewrite_predicate(predicate: Predicate) -> Predicate {
210225
match predicate {
211226
Predicate::And { args } => {
212227
let mut rewritten_args = Vec::with_capacity(args.len());
213-
for arg in args.iter() {
214-
rewritten_args.push(rewrite_predicate(arg.clone()));
228+
for arg in args.into_iter() {
229+
rewritten_args.push(rewrite_predicate(arg));
215230
}
216231
rewritten_args = flatten_and_predicates(rewritten_args);
217232
Predicate::And {
@@ -220,15 +235,13 @@ fn rewrite_predicate(predicate: Predicate) -> Predicate {
220235
}
221236
Predicate::Or { args } => {
222237
let mut rewritten_args = vec![];
223-
for arg in args.iter() {
224-
rewritten_args.push(rewrite_predicate(arg.clone()));
238+
for arg in args.into_iter() {
239+
rewritten_args.push(rewrite_predicate(arg));
225240
}
226241
rewritten_args = flatten_or_predicates(rewritten_args);
227-
delete_duplicate_predicates(&rewritten_args)
242+
delete_duplicate_predicates(rewritten_args)
228243
}
229-
Predicate::Other { expr } => Predicate::Other {
230-
expr: Box::new(*expr),
231-
},
244+
Predicate::Other { expr } => Predicate::Other { expr },
232245
}
233246
}
234247

@@ -239,8 +252,7 @@ fn flatten_and_predicates(
239252
for predicate in and_predicates {
240253
match predicate {
241254
Predicate::And { args } => {
242-
flattened_predicates
243-
.extend_from_slice(flatten_and_predicates(args).as_slice());
255+
flattened_predicates.append(&mut flatten_and_predicates(args));
244256
}
245257
_ => {
246258
flattened_predicates.push(predicate);
@@ -257,8 +269,7 @@ fn flatten_or_predicates(
257269
for predicate in or_predicates {
258270
match predicate {
259271
Predicate::Or { args } => {
260-
flattened_predicates
261-
.extend_from_slice(flatten_or_predicates(args).as_slice());
272+
flattened_predicates.append(&mut flatten_or_predicates(args));
262273
}
263274
_ => {
264275
flattened_predicates.push(predicate);
@@ -268,7 +279,7 @@ fn flatten_or_predicates(
268279
flattened_predicates
269280
}
270281

271-
fn delete_duplicate_predicates(or_predicates: &[Predicate]) -> Predicate {
282+
fn delete_duplicate_predicates(or_predicates: Vec<Predicate>) -> Predicate {
272283
let mut shortest_exprs: Vec<Predicate> = vec![];
273284
let mut shortest_exprs_len = 0;
274285
// choose the shortest AND predicate
@@ -305,31 +316,30 @@ fn delete_duplicate_predicates(or_predicates: &[Predicate]) -> Predicate {
305316
}
306317
if exist_exprs.is_empty() {
307318
return Predicate::Or {
308-
args: or_predicates.to_vec(),
319+
args: or_predicates,
309320
};
310321
}
311322

312323
// Rebuild the OR predicate.
313324
// (A AND B) OR A will be optimized to A.
314325
let mut new_or_predicates = vec![];
315-
for or_predicate in or_predicates.iter() {
326+
for or_predicate in or_predicates.into_iter() {
316327
match or_predicate {
317-
Predicate::And { args } => {
318-
let mut new_args = (*args).clone();
319-
new_args.retain(|expr| !exist_exprs.contains(expr));
320-
if !new_args.is_empty() {
321-
if new_args.len() == 1 {
322-
new_or_predicates.push(new_args[0].clone());
328+
Predicate::And { mut args } => {
329+
args.retain(|expr| !exist_exprs.contains(expr));
330+
if !args.is_empty() {
331+
if args.len() == 1 {
332+
new_or_predicates.push(args.remove(0));
323333
} else {
324-
new_or_predicates.push(Predicate::And { args: new_args });
334+
new_or_predicates.push(Predicate::And { args });
325335
}
326336
} else {
327337
new_or_predicates.clear();
328338
break;
329339
}
330340
}
331341
_ => {
332-
if exist_exprs.contains(or_predicate) {
342+
if exist_exprs.contains(&or_predicate) {
333343
new_or_predicates.clear();
334344
break;
335345
}
@@ -338,7 +348,7 @@ fn delete_duplicate_predicates(or_predicates: &[Predicate]) -> Predicate {
338348
}
339349
if !new_or_predicates.is_empty() {
340350
if new_or_predicates.len() == 1 {
341-
exist_exprs.push(new_or_predicates[0].clone());
351+
exist_exprs.push(new_or_predicates.remove(0));
342352
} else {
343353
exist_exprs.push(Predicate::Or {
344354
args: flatten_or_predicates(new_or_predicates),
@@ -347,7 +357,7 @@ fn delete_duplicate_predicates(or_predicates: &[Predicate]) -> Predicate {
347357
}
348358

349359
if exist_exprs.len() == 1 {
350-
exist_exprs[0].clone()
360+
exist_exprs.remove(0)
351361
} else {
352362
Predicate::And {
353363
args: flatten_and_predicates(exist_exprs),
@@ -373,7 +383,7 @@ mod tests {
373383
and(equi_expr.clone(), gt_expr.clone()),
374384
and(equi_expr.clone(), lt_expr.clone()),
375385
);
376-
let predicate = predicate(&expr)?;
386+
let predicate = predicate(expr)?;
377387
assert_eq!(
378388
predicate,
379389
Predicate::Or {

0 commit comments

Comments
 (0)