Skip to content

Commit

Permalink
Optimizer now simplifies multiplication when either left or right arg…
Browse files Browse the repository at this point in the history
… is a literal zero or one and division, modulo when right arg is one
  • Loading branch information
drrtuy committed Oct 10, 2022
1 parent e54110f commit c531481
Showing 1 changed file with 92 additions and 3 deletions.
95 changes: 92 additions & 3 deletions datafusion/optimizer/src/simplify_expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
use crate::expr_simplifier::ExprSimplifiable;
use crate::{expr_simplifier::SimplifyInfo, OptimizerConfig, OptimizerRule};
use arrow::array::new_null_array;
use arrow::datatypes::{DataType, Field, Schema};
use arrow::datatypes::{DataType, Field, Schema, DECIMAL128_MAX_PRECISION};
use arrow::error::ArrowError;
use arrow::record_batch::RecordBatch;
use datafusion_common::{DFSchema, DFSchemaRef, DataFusionError, Result, ScalarValue};
Expand All @@ -34,6 +34,47 @@ use datafusion_expr::{
};
use datafusion_physical_expr::{create_physical_expr, execution_props::ExecutionProps};

static POWS_OF_TEN: [i128; 38] = [
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000,
100000000000,
1000000000000,
10000000000000,
100000000000000,
1000000000000000,
10000000000000000,
100000000000000000,
1000000000000000000,
10000000000000000000,
100000000000000000000,
1000000000000000000000,
10000000000000000000000,
100000000000000000000000,
1000000000000000000000000,
10000000000000000000000000,
100000000000000000000000000,
1000000000000000000000000000,
10000000000000000000000000000,
100000000000000000000000000000,
1000000000000000000000000000000,
10000000000000000000000000000000,
100000000000000000000000000000000,
1000000000000000000000000000000000,
10000000000000000000000000000000000,
100000000000000000000000000000000000,
1000000000000000000000000000000000000,
10000000000000000000000000000000000000,
];

/// Provides simplification information based on schema and properties
pub(crate) struct SimplifyContext<'a, 'b> {
schemas: Vec<&'a DFSchemaRef>,
Expand Down Expand Up @@ -121,6 +162,7 @@ fn is_zero(s: &Expr) -> bool {
| Expr::Literal(ScalarValue::UInt64(Some(0))) => true,
Expr::Literal(ScalarValue::Float32(Some(v))) if *v == 0. => true,
Expr::Literal(ScalarValue::Float64(Some(v))) if *v == 0. => true,
Expr::Literal(ScalarValue::Decimal128(Some(v), _p, _s)) if *v == 0 => true,
_ => false,
}
}
Expand All @@ -137,6 +179,9 @@ fn is_one(s: &Expr) -> bool {
| Expr::Literal(ScalarValue::UInt64(Some(1))) => true,
Expr::Literal(ScalarValue::Float32(Some(v))) if *v == 1. => true,
Expr::Literal(ScalarValue::Float64(Some(v))) if *v == 1. => true,
Expr::Literal(ScalarValue::Decimal128(Some(v), _p, _s)) => {
*_s < DECIMAL128_MAX_PRECISION && POWS_OF_TEN[*_s as usize] == *v
}
_ => false,
}
}
Expand Down Expand Up @@ -1046,6 +1091,19 @@ mod tests {

assert_eq!(simplify(expr_a), expected);
assert_eq!(simplify(expr_b), expected);

let expr = binary_expr(
col("c2"),
Operator::Multiply,
Expr::Literal(ScalarValue::Decimal128(Some(10000000000), 38, 10)),
);
assert_eq!(simplify(expr), expected);
let expr = binary_expr(
Expr::Literal(ScalarValue::Decimal128(Some(10000000000), 31, 10)),
Operator::Multiply,
col("c2"),
);
assert_eq!(simplify(expr), expected);
}

#[test]
Expand Down Expand Up @@ -1083,13 +1141,39 @@ mod tests {
let expr = binary_expr(col("c2_non_null"), Operator::Multiply, lit(0));
assert_eq!(simplify(expr), lit(0));
}
// A * Decimal128(0) --> 0 if A is not nullable
{
let expr = binary_expr(
col("c2_non_null"),
Operator::Multiply,
Expr::Literal(ScalarValue::Decimal128(Some(0), 31, 10)),
);
assert_eq!(
simplify(expr),
Expr::Literal(ScalarValue::Decimal128(Some(0), 31, 10))
);
let expr = binary_expr(
Expr::Literal(ScalarValue::Decimal128(Some(0), 31, 10)),
Operator::Multiply,
col("c2_non_null"),
);
assert_eq!(
simplify(expr),
Expr::Literal(ScalarValue::Decimal128(Some(0), 31, 10))
);
}
}

#[test]
fn test_simplify_divide_by_one() {
let expr = binary_expr(col("c2"), Operator::Divide, lit(1));
let expected = col("c2");

assert_eq!(simplify(expr), expected);
let expr = binary_expr(
col("c2"),
Operator::Divide,
Expr::Literal(ScalarValue::Decimal128(Some(10000000000), 31, 10)),
);
assert_eq!(simplify(expr), expected);
}

Expand Down Expand Up @@ -1153,7 +1237,12 @@ mod tests {
fn test_simplify_modulo_by_one_non_null() {
let expr = binary_expr(col("c2_non_null"), Operator::Modulo, lit(1));
let expected = lit(0);

assert_eq!(simplify(expr), expected);
let expr = binary_expr(
col("c2_non_null"),
Operator::Modulo,
Expr::Literal(ScalarValue::Decimal128(Some(10000000000), 31, 10)),
);
assert_eq!(simplify(expr), expected);
}

Expand Down

0 comments on commit c531481

Please sign in to comment.