Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions datafusion/functions/src/math/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,23 +362,27 @@ impl ScalarUDFImpl for LogFunc {
} else {
lit(ScalarValue::new_ten(&number_datatype)?)
};
let base_nullable = info.nullable(&base)?;

match number {
Expr::Literal(value, _)
if value == ScalarValue::new_one(&number_datatype)? =>
if value == ScalarValue::new_one(&number_datatype)? && !base_nullable =>
{
Ok(ExprSimplifyResult::Simplified(lit(ScalarValue::new_zero(
&info.get_data_type(&base)?,
)?)))
}
Expr::ScalarFunction(ScalarFunction { func, mut args })
if is_pow(&func) && args.len() == 2 && base == args[0] =>
if is_pow(&func)
&& args.len() == 2
&& base == args[0]
&& !base_nullable =>
{
let b = args.pop().unwrap(); // length checked above
Ok(ExprSimplifyResult::Simplified(b))
}
number => {
if number == base {
if number == base && !base_nullable {
Ok(ExprSimplifyResult::Simplified(lit(ScalarValue::new_one(
&number_datatype,
)?)))
Expand Down
8 changes: 6 additions & 2 deletions datafusion/functions/src/math/power.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ impl ScalarUDFImpl for PowerFunc {
let [base, exponent] = take_function_args("power", args)?;
let base_type = info.get_data_type(&base)?;
let exponent_type = info.get_data_type(&exponent)?;
let base_nullable = info.nullable(&base)?;
let return_type =
self.return_type(&[base_type.clone(), exponent_type.clone()])?;

Expand Down Expand Up @@ -167,7 +168,7 @@ impl ScalarUDFImpl for PowerFunc {

match exponent {
Expr::Literal(value, _)
if value == ScalarValue::new_zero(&exponent_type)? =>
if value == ScalarValue::new_zero(&exponent_type)? && !base_nullable =>
{
Ok(ExprSimplifyResult::Simplified(lit(ScalarValue::new_one(
&return_type,
Expand All @@ -179,7 +180,10 @@ impl ScalarUDFImpl for PowerFunc {
)))
}
Expr::ScalarFunction(ScalarFunction { func, mut args })
if is_log(&func) && args.len() == 2 && base == args[0] =>
if is_log(&func)
&& args.len() == 2
&& base == args[0]
&& !base_nullable =>
{
let b = args.pop().unwrap(); // length checked above
let b_type = info.get_data_type(&b)?;
Expand Down
49 changes: 49 additions & 0 deletions datafusion/sqllogictest/test_files/math.slt
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,55 @@ logical_plan
02)--TableScan: aggregate_simple projection=[]
physical_plan DataSourceExec: file_groups={1 group: [[WORKSPACE_ROOT/datafusion/core/tests/data/aggregate_simple.csv]]}, projection=[NULL as log(NULL,aggregate_simple.c2)], file_type=csv, has_header=true

# Simplification must preserve NULLs from nullable columns
query RRRRR rowsort
SELECT
log(a, 1),
log(a, a),
log(a, power(a, b)),
power(a, 0),
power(a, log(a, b))
FROM (VALUES (NULL::double, 2.0::double), (2.0, 3.0)) AS t(a, b);
----
0 1 3 1 3
NULL NULL NULL NULL NULL

# Nullable bases must remain in the optimized plan so they can propagate NULL
query TT
EXPLAIN SELECT
log(a, 1) AS l1,
log(a, a) AS la,
power(a, 0) AS p0,
power(a, log(a, b)) AS pl
FROM (VALUES (NULL::double, 2.0::double), (2.0, 3.0)) AS t(a, b);
----
logical_plan
01)Projection: log(t.a, Float64(1)) AS l1, log(t.a, t.a) AS la, power(t.a, Float64(0)) AS p0, power(t.a, log(t.a, t.b)) AS pl
02)--SubqueryAlias: t
03)----Projection: column1 AS a, column2 AS b
04)------Values: (Float64(NULL) AS NULL, Float64(2)), (Float64(2), Float64(3))
physical_plan
01)ProjectionExec: expr=[log(column1@0, 1) as l1, log(column1@0, column1@0) as la, power(column1@0, 0) as p0, power(column1@0, log(column1@0, column2@1)) as pl]
02)--DataSourceExec: partitions=1, partition_sizes=[1]

# Non-nullable bases still use the existing simplifications
query TT
EXPLAIN SELECT
log(a, 1) AS l1,
log(a, a) AS la,
power(a, 0) AS p0,
power(a, log(a, b)) AS pl
FROM (VALUES (2.0::double, 3.0::double)) AS t(a, b);
----
logical_plan
01)Projection: Float64(0) AS l1, Float64(1) AS la, Float64(1) AS p0, t.b AS pl
02)--SubqueryAlias: t
03)----Projection: column2 AS b
04)------Values: (Float64(2), Float64(3))
physical_plan
01)ProjectionExec: expr=[0 as l1, 1 as la, 1 as p0, column2@1 as pl]
02)--DataSourceExec: partitions=1, partition_sizes=[1]

# Float 16/32/64 for log
query RT
SELECT log(2.5, arrow_cast(10.9, 'Float16')), arrow_typeof(log(2.5, arrow_cast(10.9, 'Float16')));
Expand Down
Loading