From fc0db9705fd1924e1a4b7c5b080d3f08383e3d48 Mon Sep 17 00:00:00 2001 From: Kunal Kundu Date: Wed, 17 Apr 2024 19:51:48 +0530 Subject: [PATCH 1/7] improve monotonicity api --- datafusion-examples/examples/advanced_udf.rs | 2 +- datafusion/expr/src/signature.rs | 27 +++++-- datafusion/functions/src/datetime/date_bin.rs | 2 +- .../functions/src/datetime/date_trunc.rs | 2 +- datafusion/functions/src/math/log.rs | 2 +- datafusion/functions/src/math/mod.rs | 76 ++++++++++++++++--- datafusion/functions/src/math/pi.rs | 2 +- datafusion/functions/src/math/round.rs | 2 +- datafusion/functions/src/math/trunc.rs | 2 +- datafusion/physical-expr/src/functions.rs | 9 ++- .../physical-expr/src/scalar_function.rs | 2 +- datafusion/physical-expr/src/udf.rs | 4 +- datafusion/physical-expr/src/utils/mod.rs | 2 +- 13 files changed, 104 insertions(+), 30 deletions(-) diff --git a/datafusion-examples/examples/advanced_udf.rs b/datafusion-examples/examples/advanced_udf.rs index c8063c0eb1e3..795946422d26 100644 --- a/datafusion-examples/examples/advanced_udf.rs +++ b/datafusion-examples/examples/advanced_udf.rs @@ -187,7 +187,7 @@ impl ScalarUDFImpl for PowUdf { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::Increasing)) } } diff --git a/datafusion/expr/src/signature.rs b/datafusion/expr/src/signature.rs index e2505d6fd65f..41aee1b5fe6b 100644 --- a/datafusion/expr/src/signature.rs +++ b/datafusion/expr/src/signature.rs @@ -346,13 +346,26 @@ impl Signature { } } -/// Monotonicity of the `ScalarFunctionExpr` with respect to its arguments. -/// Each element of this vector corresponds to an argument and indicates whether -/// the function's behavior is monotonic, or non-monotonic/unknown for that argument, namely: -/// - `None` signifies unknown monotonicity or non-monotonicity. -/// - `Some(true)` indicates that the function is monotonically increasing w.r.t. the argument in question. -/// - Some(false) indicates that the function is monotonically decreasing w.r.t. the argument in question. -pub type FuncMonotonicity = Vec>; +/// Monotonicity of a function with respect to its arguments. +/// +/// A function is [monotonic] if it preserves the relative order of its inputs. +/// +/// [monotonic]: https://en.wikipedia.org/wiki/Monotonic_function +#[derive(Debug, Clone, PartialEq)] +pub enum FuncMonotonicity { + /// not monotonic or unknown monotonicity + None, + /// Increasing with respect to all of its arguments + Increasing, + /// Decreasing with respect to all of its arguments + Decreasing, + /// Each element of this vector corresponds to an argument and indicates whether + /// the function's behavior is monotonic, or non-monotonic/unknown for that argument, namely: + /// - `None` signifies unknown monotonicity or non-monotonicity. + /// - `Some(true)` indicates that the function is monotonically increasing w.r.t. the argument in question. + /// - Some(false) indicates that the function is monotonically decreasing w.r.t. the argument in question. + Mixed(Vec>), +} #[cfg(test)] mod tests { diff --git a/datafusion/functions/src/datetime/date_bin.rs b/datafusion/functions/src/datetime/date_bin.rs index 7f5d9bb5d921..562e1800d220 100644 --- a/datafusion/functions/src/datetime/date_bin.rs +++ b/datafusion/functions/src/datetime/date_bin.rs @@ -147,7 +147,7 @@ impl ScalarUDFImpl for DateBinFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![None, Some(true)])) + Ok(Some(FuncMonotonicity::Mixed(vec![None, Some(true)]))) } } diff --git a/datafusion/functions/src/datetime/date_trunc.rs b/datafusion/functions/src/datetime/date_trunc.rs index 0414bf9c2a26..29d318c8752d 100644 --- a/datafusion/functions/src/datetime/date_trunc.rs +++ b/datafusion/functions/src/datetime/date_trunc.rs @@ -206,7 +206,7 @@ impl ScalarUDFImpl for DateTruncFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![None, Some(true)])) + Ok(Some(FuncMonotonicity::Mixed(vec![None, Some(true)]))) } } diff --git a/datafusion/functions/src/math/log.rs b/datafusion/functions/src/math/log.rs index 2131b6aa6705..b951cecdb32c 100644 --- a/datafusion/functions/src/math/log.rs +++ b/datafusion/functions/src/math/log.rs @@ -79,7 +79,7 @@ impl ScalarUDFImpl for LogFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true), Some(false)])) + Ok(Some(FuncMonotonicity::Mixed(vec![Some(true), Some(false)]))) } // Support overloaded log(base, x) and log(x) which defaults to log(10, x) diff --git a/datafusion/functions/src/math/mod.rs b/datafusion/functions/src/math/mod.rs index b6e8d26b6460..cd899782e24d 100644 --- a/datafusion/functions/src/math/mod.rs +++ b/datafusion/functions/src/math/mod.rs @@ -38,29 +38,83 @@ pub mod trunc; // Create UDFs make_udf_function!(abs::AbsFunc, ABS, abs); make_math_unary_udf!(AcosFunc, ACOS, acos, acos, None); -make_math_unary_udf!(AcoshFunc, ACOSH, acosh, acosh, Some(vec![Some(true)])); +make_math_unary_udf!( + AcoshFunc, + ACOSH, + acosh, + acosh, + Some(FuncMonotonicity::Increasing) +); make_math_unary_udf!(AsinFunc, ASIN, asin, asin, None); -make_math_unary_udf!(AsinhFunc, ASINH, asinh, asinh, Some(vec![Some(true)])); -make_math_unary_udf!(AtanFunc, ATAN, atan, atan, Some(vec![Some(true)])); -make_math_unary_udf!(AtanhFunc, ATANH, atanh, atanh, Some(vec![Some(true)])); -make_math_binary_udf!(Atan2, ATAN2, atan2, atan2, Some(vec![Some(true)])); +make_math_unary_udf!( + AsinhFunc, + ASINH, + asinh, + asinh, + Some(FuncMonotonicity::Increasing) +); +make_math_unary_udf!( + AtanFunc, + ATAN, + atan, + atan, + Some(FuncMonotonicity::Increasing) +); +make_math_unary_udf!( + AtanhFunc, + ATANH, + atanh, + atanh, + Some(FuncMonotonicity::Increasing) +); +make_math_binary_udf!( + Atan2, + ATAN2, + atan2, + atan2, + Some(FuncMonotonicity::Increasing) +); make_math_unary_udf!(CbrtFunc, CBRT, cbrt, cbrt, None); -make_math_unary_udf!(CeilFunc, CEIL, ceil, ceil, Some(vec![Some(true)])); +make_math_unary_udf!( + CeilFunc, + CEIL, + ceil, + ceil, + Some(FuncMonotonicity::Increasing) +); make_math_unary_udf!(CosFunc, COS, cos, cos, None); make_math_unary_udf!(CoshFunc, COSH, cosh, cosh, None); make_udf_function!(cot::CotFunc, COT, cot); make_math_unary_udf!(DegreesFunc, DEGREES, degrees, to_degrees, None); -make_math_unary_udf!(ExpFunc, EXP, exp, exp, Some(vec![Some(true)])); +make_math_unary_udf!(ExpFunc, EXP, exp, exp, Some(FuncMonotonicity::Increasing)); make_udf_function!(factorial::FactorialFunc, FACTORIAL, factorial); -make_math_unary_udf!(FloorFunc, FLOOR, floor, floor, Some(vec![Some(true)])); +make_math_unary_udf!( + FloorFunc, + FLOOR, + floor, + floor, + Some(FuncMonotonicity::Increasing) +); make_udf_function!(log::LogFunc, LOG, log); make_udf_function!(gcd::GcdFunc, GCD, gcd); make_udf_function!(nans::IsNanFunc, ISNAN, isnan); make_udf_function!(iszero::IsZeroFunc, ISZERO, iszero); make_udf_function!(lcm::LcmFunc, LCM, lcm); -make_math_unary_udf!(LnFunc, LN, ln, ln, Some(vec![Some(true)])); -make_math_unary_udf!(Log2Func, LOG2, log2, log2, Some(vec![Some(true)])); -make_math_unary_udf!(Log10Func, LOG10, log10, log10, Some(vec![Some(true)])); +make_math_unary_udf!(LnFunc, LN, ln, ln, Some(FuncMonotonicity::Increasing)); +make_math_unary_udf!( + Log2Func, + LOG2, + log2, + log2, + Some(FuncMonotonicity::Increasing) +); +make_math_unary_udf!( + Log10Func, + LOG10, + log10, + log10, + Some(FuncMonotonicity::Increasing) +); make_udf_function!(nanvl::NanvlFunc, NANVL, nanvl); make_udf_function!(pi::PiFunc, PI, pi); make_udf_function!(power::PowerFunc, POWER, power); diff --git a/datafusion/functions/src/math/pi.rs b/datafusion/functions/src/math/pi.rs index 0801e797511b..c444c560c03d 100644 --- a/datafusion/functions/src/math/pi.rs +++ b/datafusion/functions/src/math/pi.rs @@ -71,6 +71,6 @@ impl ScalarUDFImpl for PiFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::Increasing)) } } diff --git a/datafusion/functions/src/math/round.rs b/datafusion/functions/src/math/round.rs index f4a163137a35..7865fa1255c1 100644 --- a/datafusion/functions/src/math/round.rs +++ b/datafusion/functions/src/math/round.rs @@ -81,7 +81,7 @@ impl ScalarUDFImpl for RoundFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::Increasing)) } } diff --git a/datafusion/functions/src/math/trunc.rs b/datafusion/functions/src/math/trunc.rs index 6f88099889cc..d5bbf5a9a74e 100644 --- a/datafusion/functions/src/math/trunc.rs +++ b/datafusion/functions/src/math/trunc.rs @@ -87,7 +87,7 @@ impl ScalarUDFImpl for TruncFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::Increasing)) } } diff --git a/datafusion/physical-expr/src/functions.rs b/datafusion/physical-expr/src/functions.rs index 656ce711a0b0..58448316c6f6 100644 --- a/datafusion/physical-expr/src/functions.rs +++ b/datafusion/physical-expr/src/functions.rs @@ -223,7 +223,14 @@ pub fn out_ordering( func: &FuncMonotonicity, arg_orderings: &[SortProperties], ) -> SortProperties { - func.iter().zip(arg_orderings).fold( + let monotonicity_vec = match func { + FuncMonotonicity::None => vec![None], + FuncMonotonicity::Increasing => vec![Some(true)], + FuncMonotonicity::Decreasing => vec![Some(false)], + FuncMonotonicity::Mixed(v) => v.to_vec(), + }; + + monotonicity_vec.iter().zip(arg_orderings).fold( SortProperties::Singleton, |prev_sort, (item, arg)| { let current_sort = func_order_in_one_dimension(item, arg); diff --git a/datafusion/physical-expr/src/scalar_function.rs b/datafusion/physical-expr/src/scalar_function.rs index d34084236690..c89158deb7f0 100644 --- a/datafusion/physical-expr/src/scalar_function.rs +++ b/datafusion/physical-expr/src/scalar_function.rs @@ -54,7 +54,7 @@ pub struct ScalarFunctionExpr { args: Vec>, return_type: DataType, // Keeps monotonicity information of the function. - // FuncMonotonicity vector is one to one mapped to `args`, + // FuncMonotonicity is one to one mapped to `args`, // and it specifies the effect of an increase or decrease in // the corresponding `arg` to the function value. monotonicity: Option, diff --git a/datafusion/physical-expr/src/udf.rs b/datafusion/physical-expr/src/udf.rs index 368dfdf92f45..2c5a2d765eb0 100644 --- a/datafusion/physical-expr/src/udf.rs +++ b/datafusion/physical-expr/src/udf.rs @@ -66,7 +66,7 @@ mod tests { use arrow_schema::Schema; use datafusion_common::{DFSchema, Result}; - use datafusion_expr::ScalarUDF; + use datafusion_expr::{FuncMonotonicity, ScalarUDF}; use crate::utils::tests::TestScalarUDF; use crate::ScalarFunctionExpr; @@ -88,7 +88,7 @@ mod tests { .downcast_ref::() .unwrap() .monotonicity(), - &Some(vec![Some(true)]) + &Some(FuncMonotonicity::Increasing) ); Ok(()) diff --git a/datafusion/physical-expr/src/utils/mod.rs b/datafusion/physical-expr/src/utils/mod.rs index a0d6436586a2..ffaa04d89873 100644 --- a/datafusion/physical-expr/src/utils/mod.rs +++ b/datafusion/physical-expr/src/utils/mod.rs @@ -314,7 +314,7 @@ pub(crate) mod tests { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::Increasing)) } fn invoke(&self, args: &[ColumnarValue]) -> Result { From 349e12f77d3c1af37d9555cff07b779a5c6dddfc Mon Sep 17 00:00:00 2001 From: Kunal Kundu Date: Sun, 5 May 2024 19:45:05 +0530 Subject: [PATCH 2/7] revert "improve monotonicity api" This reverts commit fc0db9705fd1924e1a4b7c5b080d3f08383e3d48. --- datafusion-examples/examples/advanced_udf.rs | 2 +- datafusion/expr/src/signature.rs | 27 ++----- datafusion/functions/src/datetime/date_bin.rs | 2 +- .../functions/src/datetime/date_trunc.rs | 2 +- datafusion/functions/src/math/log.rs | 2 +- datafusion/functions/src/math/mod.rs | 76 +++---------------- datafusion/functions/src/math/pi.rs | 2 +- datafusion/functions/src/math/round.rs | 2 +- datafusion/functions/src/math/trunc.rs | 2 +- datafusion/physical-expr/src/functions.rs | 9 +-- .../physical-expr/src/scalar_function.rs | 2 +- datafusion/physical-expr/src/udf.rs | 4 +- datafusion/physical-expr/src/utils/mod.rs | 2 +- 13 files changed, 30 insertions(+), 104 deletions(-) diff --git a/datafusion-examples/examples/advanced_udf.rs b/datafusion-examples/examples/advanced_udf.rs index 795946422d26..c8063c0eb1e3 100644 --- a/datafusion-examples/examples/advanced_udf.rs +++ b/datafusion-examples/examples/advanced_udf.rs @@ -187,7 +187,7 @@ impl ScalarUDFImpl for PowUdf { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::Increasing)) + Ok(Some(vec![Some(true)])) } } diff --git a/datafusion/expr/src/signature.rs b/datafusion/expr/src/signature.rs index 41aee1b5fe6b..e2505d6fd65f 100644 --- a/datafusion/expr/src/signature.rs +++ b/datafusion/expr/src/signature.rs @@ -346,26 +346,13 @@ impl Signature { } } -/// Monotonicity of a function with respect to its arguments. -/// -/// A function is [monotonic] if it preserves the relative order of its inputs. -/// -/// [monotonic]: https://en.wikipedia.org/wiki/Monotonic_function -#[derive(Debug, Clone, PartialEq)] -pub enum FuncMonotonicity { - /// not monotonic or unknown monotonicity - None, - /// Increasing with respect to all of its arguments - Increasing, - /// Decreasing with respect to all of its arguments - Decreasing, - /// Each element of this vector corresponds to an argument and indicates whether - /// the function's behavior is monotonic, or non-monotonic/unknown for that argument, namely: - /// - `None` signifies unknown monotonicity or non-monotonicity. - /// - `Some(true)` indicates that the function is monotonically increasing w.r.t. the argument in question. - /// - Some(false) indicates that the function is monotonically decreasing w.r.t. the argument in question. - Mixed(Vec>), -} +/// Monotonicity of the `ScalarFunctionExpr` with respect to its arguments. +/// Each element of this vector corresponds to an argument and indicates whether +/// the function's behavior is monotonic, or non-monotonic/unknown for that argument, namely: +/// - `None` signifies unknown monotonicity or non-monotonicity. +/// - `Some(true)` indicates that the function is monotonically increasing w.r.t. the argument in question. +/// - Some(false) indicates that the function is monotonically decreasing w.r.t. the argument in question. +pub type FuncMonotonicity = Vec>; #[cfg(test)] mod tests { diff --git a/datafusion/functions/src/datetime/date_bin.rs b/datafusion/functions/src/datetime/date_bin.rs index 562e1800d220..7f5d9bb5d921 100644 --- a/datafusion/functions/src/datetime/date_bin.rs +++ b/datafusion/functions/src/datetime/date_bin.rs @@ -147,7 +147,7 @@ impl ScalarUDFImpl for DateBinFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::Mixed(vec![None, Some(true)]))) + Ok(Some(vec![None, Some(true)])) } } diff --git a/datafusion/functions/src/datetime/date_trunc.rs b/datafusion/functions/src/datetime/date_trunc.rs index 29d318c8752d..0414bf9c2a26 100644 --- a/datafusion/functions/src/datetime/date_trunc.rs +++ b/datafusion/functions/src/datetime/date_trunc.rs @@ -206,7 +206,7 @@ impl ScalarUDFImpl for DateTruncFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::Mixed(vec![None, Some(true)]))) + Ok(Some(vec![None, Some(true)])) } } diff --git a/datafusion/functions/src/math/log.rs b/datafusion/functions/src/math/log.rs index b951cecdb32c..2131b6aa6705 100644 --- a/datafusion/functions/src/math/log.rs +++ b/datafusion/functions/src/math/log.rs @@ -79,7 +79,7 @@ impl ScalarUDFImpl for LogFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::Mixed(vec![Some(true), Some(false)]))) + Ok(Some(vec![Some(true), Some(false)])) } // Support overloaded log(base, x) and log(x) which defaults to log(10, x) diff --git a/datafusion/functions/src/math/mod.rs b/datafusion/functions/src/math/mod.rs index cd899782e24d..b6e8d26b6460 100644 --- a/datafusion/functions/src/math/mod.rs +++ b/datafusion/functions/src/math/mod.rs @@ -38,83 +38,29 @@ pub mod trunc; // Create UDFs make_udf_function!(abs::AbsFunc, ABS, abs); make_math_unary_udf!(AcosFunc, ACOS, acos, acos, None); -make_math_unary_udf!( - AcoshFunc, - ACOSH, - acosh, - acosh, - Some(FuncMonotonicity::Increasing) -); +make_math_unary_udf!(AcoshFunc, ACOSH, acosh, acosh, Some(vec![Some(true)])); make_math_unary_udf!(AsinFunc, ASIN, asin, asin, None); -make_math_unary_udf!( - AsinhFunc, - ASINH, - asinh, - asinh, - Some(FuncMonotonicity::Increasing) -); -make_math_unary_udf!( - AtanFunc, - ATAN, - atan, - atan, - Some(FuncMonotonicity::Increasing) -); -make_math_unary_udf!( - AtanhFunc, - ATANH, - atanh, - atanh, - Some(FuncMonotonicity::Increasing) -); -make_math_binary_udf!( - Atan2, - ATAN2, - atan2, - atan2, - Some(FuncMonotonicity::Increasing) -); +make_math_unary_udf!(AsinhFunc, ASINH, asinh, asinh, Some(vec![Some(true)])); +make_math_unary_udf!(AtanFunc, ATAN, atan, atan, Some(vec![Some(true)])); +make_math_unary_udf!(AtanhFunc, ATANH, atanh, atanh, Some(vec![Some(true)])); +make_math_binary_udf!(Atan2, ATAN2, atan2, atan2, Some(vec![Some(true)])); make_math_unary_udf!(CbrtFunc, CBRT, cbrt, cbrt, None); -make_math_unary_udf!( - CeilFunc, - CEIL, - ceil, - ceil, - Some(FuncMonotonicity::Increasing) -); +make_math_unary_udf!(CeilFunc, CEIL, ceil, ceil, Some(vec![Some(true)])); make_math_unary_udf!(CosFunc, COS, cos, cos, None); make_math_unary_udf!(CoshFunc, COSH, cosh, cosh, None); make_udf_function!(cot::CotFunc, COT, cot); make_math_unary_udf!(DegreesFunc, DEGREES, degrees, to_degrees, None); -make_math_unary_udf!(ExpFunc, EXP, exp, exp, Some(FuncMonotonicity::Increasing)); +make_math_unary_udf!(ExpFunc, EXP, exp, exp, Some(vec![Some(true)])); make_udf_function!(factorial::FactorialFunc, FACTORIAL, factorial); -make_math_unary_udf!( - FloorFunc, - FLOOR, - floor, - floor, - Some(FuncMonotonicity::Increasing) -); +make_math_unary_udf!(FloorFunc, FLOOR, floor, floor, Some(vec![Some(true)])); make_udf_function!(log::LogFunc, LOG, log); make_udf_function!(gcd::GcdFunc, GCD, gcd); make_udf_function!(nans::IsNanFunc, ISNAN, isnan); make_udf_function!(iszero::IsZeroFunc, ISZERO, iszero); make_udf_function!(lcm::LcmFunc, LCM, lcm); -make_math_unary_udf!(LnFunc, LN, ln, ln, Some(FuncMonotonicity::Increasing)); -make_math_unary_udf!( - Log2Func, - LOG2, - log2, - log2, - Some(FuncMonotonicity::Increasing) -); -make_math_unary_udf!( - Log10Func, - LOG10, - log10, - log10, - Some(FuncMonotonicity::Increasing) -); +make_math_unary_udf!(LnFunc, LN, ln, ln, Some(vec![Some(true)])); +make_math_unary_udf!(Log2Func, LOG2, log2, log2, Some(vec![Some(true)])); +make_math_unary_udf!(Log10Func, LOG10, log10, log10, Some(vec![Some(true)])); make_udf_function!(nanvl::NanvlFunc, NANVL, nanvl); make_udf_function!(pi::PiFunc, PI, pi); make_udf_function!(power::PowerFunc, POWER, power); diff --git a/datafusion/functions/src/math/pi.rs b/datafusion/functions/src/math/pi.rs index c444c560c03d..0801e797511b 100644 --- a/datafusion/functions/src/math/pi.rs +++ b/datafusion/functions/src/math/pi.rs @@ -71,6 +71,6 @@ impl ScalarUDFImpl for PiFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::Increasing)) + Ok(Some(vec![Some(true)])) } } diff --git a/datafusion/functions/src/math/round.rs b/datafusion/functions/src/math/round.rs index 7865fa1255c1..f4a163137a35 100644 --- a/datafusion/functions/src/math/round.rs +++ b/datafusion/functions/src/math/round.rs @@ -81,7 +81,7 @@ impl ScalarUDFImpl for RoundFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::Increasing)) + Ok(Some(vec![Some(true)])) } } diff --git a/datafusion/functions/src/math/trunc.rs b/datafusion/functions/src/math/trunc.rs index d5bbf5a9a74e..6f88099889cc 100644 --- a/datafusion/functions/src/math/trunc.rs +++ b/datafusion/functions/src/math/trunc.rs @@ -87,7 +87,7 @@ impl ScalarUDFImpl for TruncFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::Increasing)) + Ok(Some(vec![Some(true)])) } } diff --git a/datafusion/physical-expr/src/functions.rs b/datafusion/physical-expr/src/functions.rs index 58448316c6f6..656ce711a0b0 100644 --- a/datafusion/physical-expr/src/functions.rs +++ b/datafusion/physical-expr/src/functions.rs @@ -223,14 +223,7 @@ pub fn out_ordering( func: &FuncMonotonicity, arg_orderings: &[SortProperties], ) -> SortProperties { - let monotonicity_vec = match func { - FuncMonotonicity::None => vec![None], - FuncMonotonicity::Increasing => vec![Some(true)], - FuncMonotonicity::Decreasing => vec![Some(false)], - FuncMonotonicity::Mixed(v) => v.to_vec(), - }; - - monotonicity_vec.iter().zip(arg_orderings).fold( + func.iter().zip(arg_orderings).fold( SortProperties::Singleton, |prev_sort, (item, arg)| { let current_sort = func_order_in_one_dimension(item, arg); diff --git a/datafusion/physical-expr/src/scalar_function.rs b/datafusion/physical-expr/src/scalar_function.rs index c89158deb7f0..d34084236690 100644 --- a/datafusion/physical-expr/src/scalar_function.rs +++ b/datafusion/physical-expr/src/scalar_function.rs @@ -54,7 +54,7 @@ pub struct ScalarFunctionExpr { args: Vec>, return_type: DataType, // Keeps monotonicity information of the function. - // FuncMonotonicity is one to one mapped to `args`, + // FuncMonotonicity vector is one to one mapped to `args`, // and it specifies the effect of an increase or decrease in // the corresponding `arg` to the function value. monotonicity: Option, diff --git a/datafusion/physical-expr/src/udf.rs b/datafusion/physical-expr/src/udf.rs index 2c5a2d765eb0..368dfdf92f45 100644 --- a/datafusion/physical-expr/src/udf.rs +++ b/datafusion/physical-expr/src/udf.rs @@ -66,7 +66,7 @@ mod tests { use arrow_schema::Schema; use datafusion_common::{DFSchema, Result}; - use datafusion_expr::{FuncMonotonicity, ScalarUDF}; + use datafusion_expr::ScalarUDF; use crate::utils::tests::TestScalarUDF; use crate::ScalarFunctionExpr; @@ -88,7 +88,7 @@ mod tests { .downcast_ref::() .unwrap() .monotonicity(), - &Some(FuncMonotonicity::Increasing) + &Some(vec![Some(true)]) ); Ok(()) diff --git a/datafusion/physical-expr/src/utils/mod.rs b/datafusion/physical-expr/src/utils/mod.rs index ffaa04d89873..a0d6436586a2 100644 --- a/datafusion/physical-expr/src/utils/mod.rs +++ b/datafusion/physical-expr/src/utils/mod.rs @@ -314,7 +314,7 @@ pub(crate) mod tests { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::Increasing)) + Ok(Some(vec![Some(true)])) } fn invoke(&self, args: &[ColumnarValue]) -> Result { From b77eabb782b71854451216407cbb3d3cd06911c7 Mon Sep 17 00:00:00 2001 From: Kunal Kundu Date: Mon, 6 May 2024 01:19:16 +0530 Subject: [PATCH 3/7] implement new api --- datafusion-examples/examples/advanced_udf.rs | 2 +- datafusion/expr/src/signature.rs | 76 +++++++++++++++-- datafusion/functions/src/datetime/date_bin.rs | 2 +- .../functions/src/datetime/date_trunc.rs | 2 +- datafusion/functions/src/math/log.rs | 5 +- datafusion/functions/src/math/mod.rs | 82 ++++++++++++++++--- datafusion/functions/src/math/pi.rs | 2 +- datafusion/functions/src/math/round.rs | 2 +- datafusion/functions/src/math/trunc.rs | 2 +- datafusion/physical-expr/src/functions.rs | 3 +- datafusion/physical-expr/src/udf.rs | 4 +- datafusion/physical-expr/src/utils/mod.rs | 2 +- 12 files changed, 155 insertions(+), 29 deletions(-) diff --git a/datafusion-examples/examples/advanced_udf.rs b/datafusion-examples/examples/advanced_udf.rs index c8063c0eb1e3..fbc19043cccf 100644 --- a/datafusion-examples/examples/advanced_udf.rs +++ b/datafusion-examples/examples/advanced_udf.rs @@ -187,7 +187,7 @@ impl ScalarUDFImpl for PowUdf { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::new_increasing())) } } diff --git a/datafusion/expr/src/signature.rs b/datafusion/expr/src/signature.rs index e2505d6fd65f..d55a24f1e51b 100644 --- a/datafusion/expr/src/signature.rs +++ b/datafusion/expr/src/signature.rs @@ -346,13 +346,75 @@ impl Signature { } } -/// Monotonicity of the `ScalarFunctionExpr` with respect to its arguments. -/// Each element of this vector corresponds to an argument and indicates whether -/// the function's behavior is monotonic, or non-monotonic/unknown for that argument, namely: -/// - `None` signifies unknown monotonicity or non-monotonicity. -/// - `Some(true)` indicates that the function is monotonically increasing w.r.t. the argument in question. -/// - Some(false) indicates that the function is monotonically decreasing w.r.t. the argument in question. -pub type FuncMonotonicity = Vec>; +#[derive(Debug, Clone, PartialEq)] +enum FuncMonotonicityPartial { + /// not monotonic or unknown monotonicity + None, + /// Increasing with respect to all of its arguments + Increasing, + /// Decreasing with respect to all of its arguments + Decreasing, + /// Each element of this vector corresponds to an argument and indicates whether + /// the function's behavior is monotonic, or non-monotonic/unknown for that argument, namely: + /// - `None` signifies unknown monotonicity or non-monotonicity. + /// - `Some(true)` indicates that the function is monotonically increasing w.r.t. the argument in question. + /// - Some(false) indicates that the function is monotonically decreasing w.r.t. the argument in question. + Mixed(Vec>), +} + +/// Monotonicity of a function with respect to its arguments. +/// +/// A function is [monotonic] if it preserves the relative order of its inputs. +/// +/// [monotonic]: https://en.wikipedia.org/wiki/Monotonic_function +#[derive(Debug, Clone, PartialEq)] +pub struct FuncMonotonicity(FuncMonotonicityPartial); + +impl FuncMonotonicity { + pub fn new_none() -> Self { + Self(FuncMonotonicityPartial::None) + } + pub fn new_increasing() -> Self { + Self(FuncMonotonicityPartial::Increasing) + } + pub fn new_decreasing() -> Self { + Self(FuncMonotonicityPartial::Decreasing) + } + pub fn new_mixed(inner: Vec>) -> Self { + Self(FuncMonotonicityPartial::Mixed(inner)) + } + + /// returns true if this function is monotonically increasing with respect to argument number arg + pub fn arg_increasing(&self, arg: usize) -> bool { + match &self.0 { + FuncMonotonicityPartial::None => false, + FuncMonotonicityPartial::Increasing => true, + FuncMonotonicityPartial::Decreasing => false, + FuncMonotonicityPartial::Mixed(inner) => inner[arg].unwrap_or(false), + } + } + + /// returns true if this function is monotonically decreasing with respect to argument number arg + pub fn arg_decreasing(&self, arg: usize) -> bool { + match &self.0 { + FuncMonotonicityPartial::None => false, + FuncMonotonicityPartial::Increasing => false, + FuncMonotonicityPartial::Decreasing => true, + FuncMonotonicityPartial::Mixed(inner) => inner[arg].unwrap_or(false), + } + } +} + +impl From<&FuncMonotonicity> for Vec> { + fn from(val: &FuncMonotonicity) -> Self { + match &val.0 { + FuncMonotonicityPartial::None => vec![None], + FuncMonotonicityPartial::Increasing => vec![Some(true)], + FuncMonotonicityPartial::Decreasing => vec![Some(false)], + FuncMonotonicityPartial::Mixed(inner) => inner.to_vec(), + } + } +} #[cfg(test)] mod tests { diff --git a/datafusion/functions/src/datetime/date_bin.rs b/datafusion/functions/src/datetime/date_bin.rs index da1797cdae81..fbf694f40717 100644 --- a/datafusion/functions/src/datetime/date_bin.rs +++ b/datafusion/functions/src/datetime/date_bin.rs @@ -147,7 +147,7 @@ impl ScalarUDFImpl for DateBinFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![None, Some(true)])) + Ok(Some(FuncMonotonicity::new_mixed(vec![None, Some(true)]))) } } diff --git a/datafusion/functions/src/datetime/date_trunc.rs b/datafusion/functions/src/datetime/date_trunc.rs index 0414bf9c2a26..afe6127c2eb1 100644 --- a/datafusion/functions/src/datetime/date_trunc.rs +++ b/datafusion/functions/src/datetime/date_trunc.rs @@ -206,7 +206,7 @@ impl ScalarUDFImpl for DateTruncFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![None, Some(true)])) + Ok(Some(FuncMonotonicity::new_mixed(vec![None, Some(true)]))) } } diff --git a/datafusion/functions/src/math/log.rs b/datafusion/functions/src/math/log.rs index f451321ea120..34e6d3abfd51 100644 --- a/datafusion/functions/src/math/log.rs +++ b/datafusion/functions/src/math/log.rs @@ -84,7 +84,10 @@ impl ScalarUDFImpl for LogFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true), Some(false)])) + Ok(Some(FuncMonotonicity::new_mixed(vec![ + Some(true), + Some(false), + ]))) } // Support overloaded log(base, x) and log(x) which defaults to log(10, x) diff --git a/datafusion/functions/src/math/mod.rs b/datafusion/functions/src/math/mod.rs index b6e8d26b6460..96d042e91913 100644 --- a/datafusion/functions/src/math/mod.rs +++ b/datafusion/functions/src/math/mod.rs @@ -38,29 +38,89 @@ pub mod trunc; // Create UDFs make_udf_function!(abs::AbsFunc, ABS, abs); make_math_unary_udf!(AcosFunc, ACOS, acos, acos, None); -make_math_unary_udf!(AcoshFunc, ACOSH, acosh, acosh, Some(vec![Some(true)])); +make_math_unary_udf!( + AcoshFunc, + ACOSH, + acosh, + acosh, + Some(FuncMonotonicity::new_increasing()) +); make_math_unary_udf!(AsinFunc, ASIN, asin, asin, None); -make_math_unary_udf!(AsinhFunc, ASINH, asinh, asinh, Some(vec![Some(true)])); -make_math_unary_udf!(AtanFunc, ATAN, atan, atan, Some(vec![Some(true)])); -make_math_unary_udf!(AtanhFunc, ATANH, atanh, atanh, Some(vec![Some(true)])); -make_math_binary_udf!(Atan2, ATAN2, atan2, atan2, Some(vec![Some(true)])); +make_math_unary_udf!( + AsinhFunc, + ASINH, + asinh, + asinh, + Some(FuncMonotonicity::new_increasing()) +); +make_math_unary_udf!( + AtanFunc, + ATAN, + atan, + atan, + Some(FuncMonotonicity::new_increasing()) +); +make_math_unary_udf!( + AtanhFunc, + ATANH, + atanh, + atanh, + Some(FuncMonotonicity::new_increasing()) +); +make_math_binary_udf!( + Atan2, + ATAN2, + atan2, + atan2, + Some(FuncMonotonicity::new_increasing()) +); make_math_unary_udf!(CbrtFunc, CBRT, cbrt, cbrt, None); -make_math_unary_udf!(CeilFunc, CEIL, ceil, ceil, Some(vec![Some(true)])); +make_math_unary_udf!( + CeilFunc, + CEIL, + ceil, + ceil, + Some(FuncMonotonicity::new_increasing()) +); make_math_unary_udf!(CosFunc, COS, cos, cos, None); make_math_unary_udf!(CoshFunc, COSH, cosh, cosh, None); make_udf_function!(cot::CotFunc, COT, cot); make_math_unary_udf!(DegreesFunc, DEGREES, degrees, to_degrees, None); -make_math_unary_udf!(ExpFunc, EXP, exp, exp, Some(vec![Some(true)])); +make_math_unary_udf!( + ExpFunc, + EXP, + exp, + exp, + Some(FuncMonotonicity::new_increasing()) +); make_udf_function!(factorial::FactorialFunc, FACTORIAL, factorial); -make_math_unary_udf!(FloorFunc, FLOOR, floor, floor, Some(vec![Some(true)])); +make_math_unary_udf!( + FloorFunc, + FLOOR, + floor, + floor, + Some(FuncMonotonicity::new_increasing()) +); make_udf_function!(log::LogFunc, LOG, log); make_udf_function!(gcd::GcdFunc, GCD, gcd); make_udf_function!(nans::IsNanFunc, ISNAN, isnan); make_udf_function!(iszero::IsZeroFunc, ISZERO, iszero); make_udf_function!(lcm::LcmFunc, LCM, lcm); -make_math_unary_udf!(LnFunc, LN, ln, ln, Some(vec![Some(true)])); -make_math_unary_udf!(Log2Func, LOG2, log2, log2, Some(vec![Some(true)])); -make_math_unary_udf!(Log10Func, LOG10, log10, log10, Some(vec![Some(true)])); +make_math_unary_udf!(LnFunc, LN, ln, ln, Some(FuncMonotonicity::new_increasing())); +make_math_unary_udf!( + Log2Func, + LOG2, + log2, + log2, + Some(FuncMonotonicity::new_increasing()) +); +make_math_unary_udf!( + Log10Func, + LOG10, + log10, + log10, + Some(FuncMonotonicity::new_increasing()) +); make_udf_function!(nanvl::NanvlFunc, NANVL, nanvl); make_udf_function!(pi::PiFunc, PI, pi); make_udf_function!(power::PowerFunc, POWER, power); diff --git a/datafusion/functions/src/math/pi.rs b/datafusion/functions/src/math/pi.rs index f9403e411fe2..cd2060805915 100644 --- a/datafusion/functions/src/math/pi.rs +++ b/datafusion/functions/src/math/pi.rs @@ -71,6 +71,6 @@ impl ScalarUDFImpl for PiFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::new_increasing())) } } diff --git a/datafusion/functions/src/math/round.rs b/datafusion/functions/src/math/round.rs index f4a163137a35..56c303806ed8 100644 --- a/datafusion/functions/src/math/round.rs +++ b/datafusion/functions/src/math/round.rs @@ -81,7 +81,7 @@ impl ScalarUDFImpl for RoundFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::new_increasing())) } } diff --git a/datafusion/functions/src/math/trunc.rs b/datafusion/functions/src/math/trunc.rs index 6f88099889cc..f4a5ebd90adf 100644 --- a/datafusion/functions/src/math/trunc.rs +++ b/datafusion/functions/src/math/trunc.rs @@ -87,7 +87,7 @@ impl ScalarUDFImpl for TruncFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::new_increasing())) } } diff --git a/datafusion/physical-expr/src/functions.rs b/datafusion/physical-expr/src/functions.rs index 06c4bd1c9531..7e7d7b678d9b 100644 --- a/datafusion/physical-expr/src/functions.rs +++ b/datafusion/physical-expr/src/functions.rs @@ -171,7 +171,8 @@ pub fn out_ordering( func: &FuncMonotonicity, arg_orderings: &[SortProperties], ) -> SortProperties { - func.iter().zip(arg_orderings).fold( + let monotonicity_vec: Vec> = func.into(); + monotonicity_vec.iter().zip(arg_orderings).fold( SortProperties::Singleton, |prev_sort, (item, arg)| { let current_sort = func_order_in_one_dimension(item, arg); diff --git a/datafusion/physical-expr/src/udf.rs b/datafusion/physical-expr/src/udf.rs index aad78b7c2f90..716fe8122903 100644 --- a/datafusion/physical-expr/src/udf.rs +++ b/datafusion/physical-expr/src/udf.rs @@ -65,7 +65,7 @@ mod tests { use arrow_schema::Schema; use datafusion_common::{DFSchema, Result}; - use datafusion_expr::ScalarUDF; + use datafusion_expr::{FuncMonotonicity, ScalarUDF}; use crate::utils::tests::TestScalarUDF; use crate::ScalarFunctionExpr; @@ -87,7 +87,7 @@ mod tests { .downcast_ref::() .unwrap() .monotonicity(), - &Some(vec![Some(true)]) + &Some(FuncMonotonicity::new_increasing()) ); Ok(()) diff --git a/datafusion/physical-expr/src/utils/mod.rs b/datafusion/physical-expr/src/utils/mod.rs index 76cee3a1a786..f72ff82d90e9 100644 --- a/datafusion/physical-expr/src/utils/mod.rs +++ b/datafusion/physical-expr/src/utils/mod.rs @@ -310,7 +310,7 @@ pub(crate) mod tests { } fn monotonicity(&self) -> Result> { - Ok(Some(vec![Some(true)])) + Ok(Some(FuncMonotonicity::new_increasing())) } fn invoke(&self, args: &[ColumnarValue]) -> Result { From d47b89664df19ebcd59ad2aae4b8f6d0572f08fd Mon Sep 17 00:00:00 2001 From: Kunal Kundu Date: Mon, 6 May 2024 14:35:11 +0530 Subject: [PATCH 4/7] implement PartialEq for FuncMonotonicity --- datafusion/expr/src/signature.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/datafusion/expr/src/signature.rs b/datafusion/expr/src/signature.rs index d55a24f1e51b..faa2dc5bb4f3 100644 --- a/datafusion/expr/src/signature.rs +++ b/datafusion/expr/src/signature.rs @@ -346,7 +346,7 @@ impl Signature { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone)] enum FuncMonotonicityPartial { /// not monotonic or unknown monotonicity None, @@ -367,7 +367,7 @@ enum FuncMonotonicityPartial { /// A function is [monotonic] if it preserves the relative order of its inputs. /// /// [monotonic]: https://en.wikipedia.org/wiki/Monotonic_function -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone)] pub struct FuncMonotonicity(FuncMonotonicityPartial); impl FuncMonotonicity { @@ -416,6 +416,12 @@ impl From<&FuncMonotonicity> for Vec> { } } +impl PartialEq for FuncMonotonicity { + fn eq(&self, other: &Self) -> bool { + Into::>>::into(self) == Into::>>::into(other) + } +} + #[cfg(test)] mod tests { use super::*; From 1266ed87ba00a7ec0ce7791843bbe925ef6be881 Mon Sep 17 00:00:00 2001 From: Kunal Kundu Date: Tue, 7 May 2024 13:40:09 +0530 Subject: [PATCH 5/7] remove unused apis --- datafusion/expr/src/signature.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/datafusion/expr/src/signature.rs b/datafusion/expr/src/signature.rs index faa2dc5bb4f3..dcd83899364f 100644 --- a/datafusion/expr/src/signature.rs +++ b/datafusion/expr/src/signature.rs @@ -383,26 +383,6 @@ impl FuncMonotonicity { pub fn new_mixed(inner: Vec>) -> Self { Self(FuncMonotonicityPartial::Mixed(inner)) } - - /// returns true if this function is monotonically increasing with respect to argument number arg - pub fn arg_increasing(&self, arg: usize) -> bool { - match &self.0 { - FuncMonotonicityPartial::None => false, - FuncMonotonicityPartial::Increasing => true, - FuncMonotonicityPartial::Decreasing => false, - FuncMonotonicityPartial::Mixed(inner) => inner[arg].unwrap_or(false), - } - } - - /// returns true if this function is monotonically decreasing with respect to argument number arg - pub fn arg_decreasing(&self, arg: usize) -> bool { - match &self.0 { - FuncMonotonicityPartial::None => false, - FuncMonotonicityPartial::Increasing => false, - FuncMonotonicityPartial::Decreasing => true, - FuncMonotonicityPartial::Mixed(inner) => inner[arg].unwrap_or(false), - } - } } impl From<&FuncMonotonicity> for Vec> { From ea21acd6156b59ff1abc766f4cd68f131e67569b Mon Sep 17 00:00:00 2001 From: Kunal Kundu Date: Thu, 9 May 2024 17:33:14 +0530 Subject: [PATCH 6/7] implement matches, fix PartialEq for monotoncity --- datafusion-examples/examples/advanced_udf.rs | 2 +- datafusion/expr/src/signature.rs | 67 +++++++++---------- datafusion/functions/src/datetime/date_bin.rs | 2 +- .../functions/src/datetime/date_trunc.rs | 2 +- datafusion/functions/src/math/log.rs | 5 +- datafusion/functions/src/math/mod.rs | 28 +++----- datafusion/functions/src/math/pi.rs | 2 +- datafusion/functions/src/math/round.rs | 2 +- datafusion/functions/src/math/trunc.rs | 2 +- .../physical-expr/src/scalar_function.rs | 57 ++++++++++++++-- datafusion/physical-expr/src/utils/mod.rs | 2 +- 11 files changed, 104 insertions(+), 67 deletions(-) diff --git a/datafusion-examples/examples/advanced_udf.rs b/datafusion-examples/examples/advanced_udf.rs index fbc19043cccf..795946422d26 100644 --- a/datafusion-examples/examples/advanced_udf.rs +++ b/datafusion-examples/examples/advanced_udf.rs @@ -187,7 +187,7 @@ impl ScalarUDFImpl for PowUdf { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::new_increasing())) + Ok(Some(FuncMonotonicity::Increasing)) } } diff --git a/datafusion/expr/src/signature.rs b/datafusion/expr/src/signature.rs index dcd83899364f..c3d53e94501f 100644 --- a/datafusion/expr/src/signature.rs +++ b/datafusion/expr/src/signature.rs @@ -346,8 +346,13 @@ impl Signature { } } +/// Monotonicity of a function with respect to its arguments. +/// +/// A function is [monotonic] if it preserves the relative order of its inputs. +/// +/// [monotonic]: https://en.wikipedia.org/wiki/Monotonic_function #[derive(Debug, Clone)] -enum FuncMonotonicityPartial { +pub enum FuncMonotonicity { /// not monotonic or unknown monotonicity None, /// Increasing with respect to all of its arguments @@ -362,43 +367,37 @@ enum FuncMonotonicityPartial { Mixed(Vec>), } -/// Monotonicity of a function with respect to its arguments. -/// -/// A function is [monotonic] if it preserves the relative order of its inputs. -/// -/// [monotonic]: https://en.wikipedia.org/wiki/Monotonic_function -#[derive(Debug, Clone)] -pub struct FuncMonotonicity(FuncMonotonicityPartial); - -impl FuncMonotonicity { - pub fn new_none() -> Self { - Self(FuncMonotonicityPartial::None) - } - pub fn new_increasing() -> Self { - Self(FuncMonotonicityPartial::Increasing) - } - pub fn new_decreasing() -> Self { - Self(FuncMonotonicityPartial::Decreasing) - } - pub fn new_mixed(inner: Vec>) -> Self { - Self(FuncMonotonicityPartial::Mixed(inner)) - } -} - -impl From<&FuncMonotonicity> for Vec> { - fn from(val: &FuncMonotonicity) -> Self { - match &val.0 { - FuncMonotonicityPartial::None => vec![None], - FuncMonotonicityPartial::Increasing => vec![Some(true)], - FuncMonotonicityPartial::Decreasing => vec![Some(false)], - FuncMonotonicityPartial::Mixed(inner) => inner.to_vec(), +impl PartialEq for FuncMonotonicity { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (FuncMonotonicity::None, FuncMonotonicity::None) => true, + (FuncMonotonicity::Increasing, FuncMonotonicity::Increasing) => true, + (FuncMonotonicity::Decreasing, FuncMonotonicity::Decreasing) => true, + (FuncMonotonicity::Mixed(vec1), FuncMonotonicity::Mixed(vec2)) => { + vec1 == vec2 + } + _ => false, } } } -impl PartialEq for FuncMonotonicity { - fn eq(&self, other: &Self) -> bool { - Into::>>::into(self) == Into::>>::into(other) +impl FuncMonotonicity { + pub fn matches(&self, other: &Self) -> bool { + match (self, other) { + (FuncMonotonicity::None, FuncMonotonicity::Mixed(inner_vec)) + | (FuncMonotonicity::Mixed(inner_vec), FuncMonotonicity::None) => { + inner_vec.iter().all(|&x| x == None) + } + (FuncMonotonicity::Increasing, FuncMonotonicity::Mixed(inner_vec)) + | (FuncMonotonicity::Mixed(inner_vec), FuncMonotonicity::Increasing) => { + inner_vec.iter().all(|&x| x == Some(true)) + } + (FuncMonotonicity::Decreasing, FuncMonotonicity::Mixed(inner_vec)) + | (FuncMonotonicity::Mixed(inner_vec), FuncMonotonicity::Decreasing) => { + inner_vec.iter().all(|&x| x == Some(false)) + } + _ => self == other, + } } } diff --git a/datafusion/functions/src/datetime/date_bin.rs b/datafusion/functions/src/datetime/date_bin.rs index fbf694f40717..df3c7aff1881 100644 --- a/datafusion/functions/src/datetime/date_bin.rs +++ b/datafusion/functions/src/datetime/date_bin.rs @@ -147,7 +147,7 @@ impl ScalarUDFImpl for DateBinFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::new_mixed(vec![None, Some(true)]))) + Ok(Some(FuncMonotonicity::Mixed(vec![None, Some(true)]))) } } diff --git a/datafusion/functions/src/datetime/date_trunc.rs b/datafusion/functions/src/datetime/date_trunc.rs index afe6127c2eb1..29d318c8752d 100644 --- a/datafusion/functions/src/datetime/date_trunc.rs +++ b/datafusion/functions/src/datetime/date_trunc.rs @@ -206,7 +206,7 @@ impl ScalarUDFImpl for DateTruncFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::new_mixed(vec![None, Some(true)]))) + Ok(Some(FuncMonotonicity::Mixed(vec![None, Some(true)]))) } } diff --git a/datafusion/functions/src/math/log.rs b/datafusion/functions/src/math/log.rs index 34e6d3abfd51..5009d900007b 100644 --- a/datafusion/functions/src/math/log.rs +++ b/datafusion/functions/src/math/log.rs @@ -84,10 +84,7 @@ impl ScalarUDFImpl for LogFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::new_mixed(vec![ - Some(true), - Some(false), - ]))) + Ok(Some(FuncMonotonicity::Mixed(vec![Some(true), Some(false)]))) } // Support overloaded log(base, x) and log(x) which defaults to log(10, x) diff --git a/datafusion/functions/src/math/mod.rs b/datafusion/functions/src/math/mod.rs index 96d042e91913..cd899782e24d 100644 --- a/datafusion/functions/src/math/mod.rs +++ b/datafusion/functions/src/math/mod.rs @@ -43,7 +43,7 @@ make_math_unary_udf!( ACOSH, acosh, acosh, - Some(FuncMonotonicity::new_increasing()) + Some(FuncMonotonicity::Increasing) ); make_math_unary_udf!(AsinFunc, ASIN, asin, asin, None); make_math_unary_udf!( @@ -51,28 +51,28 @@ make_math_unary_udf!( ASINH, asinh, asinh, - Some(FuncMonotonicity::new_increasing()) + Some(FuncMonotonicity::Increasing) ); make_math_unary_udf!( AtanFunc, ATAN, atan, atan, - Some(FuncMonotonicity::new_increasing()) + Some(FuncMonotonicity::Increasing) ); make_math_unary_udf!( AtanhFunc, ATANH, atanh, atanh, - Some(FuncMonotonicity::new_increasing()) + Some(FuncMonotonicity::Increasing) ); make_math_binary_udf!( Atan2, ATAN2, atan2, atan2, - Some(FuncMonotonicity::new_increasing()) + Some(FuncMonotonicity::Increasing) ); make_math_unary_udf!(CbrtFunc, CBRT, cbrt, cbrt, None); make_math_unary_udf!( @@ -80,46 +80,40 @@ make_math_unary_udf!( CEIL, ceil, ceil, - Some(FuncMonotonicity::new_increasing()) + Some(FuncMonotonicity::Increasing) ); make_math_unary_udf!(CosFunc, COS, cos, cos, None); make_math_unary_udf!(CoshFunc, COSH, cosh, cosh, None); make_udf_function!(cot::CotFunc, COT, cot); make_math_unary_udf!(DegreesFunc, DEGREES, degrees, to_degrees, None); -make_math_unary_udf!( - ExpFunc, - EXP, - exp, - exp, - Some(FuncMonotonicity::new_increasing()) -); +make_math_unary_udf!(ExpFunc, EXP, exp, exp, Some(FuncMonotonicity::Increasing)); make_udf_function!(factorial::FactorialFunc, FACTORIAL, factorial); make_math_unary_udf!( FloorFunc, FLOOR, floor, floor, - Some(FuncMonotonicity::new_increasing()) + Some(FuncMonotonicity::Increasing) ); make_udf_function!(log::LogFunc, LOG, log); make_udf_function!(gcd::GcdFunc, GCD, gcd); make_udf_function!(nans::IsNanFunc, ISNAN, isnan); make_udf_function!(iszero::IsZeroFunc, ISZERO, iszero); make_udf_function!(lcm::LcmFunc, LCM, lcm); -make_math_unary_udf!(LnFunc, LN, ln, ln, Some(FuncMonotonicity::new_increasing())); +make_math_unary_udf!(LnFunc, LN, ln, ln, Some(FuncMonotonicity::Increasing)); make_math_unary_udf!( Log2Func, LOG2, log2, log2, - Some(FuncMonotonicity::new_increasing()) + Some(FuncMonotonicity::Increasing) ); make_math_unary_udf!( Log10Func, LOG10, log10, log10, - Some(FuncMonotonicity::new_increasing()) + Some(FuncMonotonicity::Increasing) ); make_udf_function!(nanvl::NanvlFunc, NANVL, nanvl); make_udf_function!(pi::PiFunc, PI, pi); diff --git a/datafusion/functions/src/math/pi.rs b/datafusion/functions/src/math/pi.rs index cd2060805915..a840baf93bcf 100644 --- a/datafusion/functions/src/math/pi.rs +++ b/datafusion/functions/src/math/pi.rs @@ -71,6 +71,6 @@ impl ScalarUDFImpl for PiFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::new_increasing())) + Ok(Some(FuncMonotonicity::Increasing)) } } diff --git a/datafusion/functions/src/math/round.rs b/datafusion/functions/src/math/round.rs index 56c303806ed8..7865fa1255c1 100644 --- a/datafusion/functions/src/math/round.rs +++ b/datafusion/functions/src/math/round.rs @@ -81,7 +81,7 @@ impl ScalarUDFImpl for RoundFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::new_increasing())) + Ok(Some(FuncMonotonicity::Increasing)) } } diff --git a/datafusion/functions/src/math/trunc.rs b/datafusion/functions/src/math/trunc.rs index f4a5ebd90adf..d5bbf5a9a74e 100644 --- a/datafusion/functions/src/math/trunc.rs +++ b/datafusion/functions/src/math/trunc.rs @@ -87,7 +87,7 @@ impl ScalarUDFImpl for TruncFunc { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::new_increasing())) + Ok(Some(FuncMonotonicity::Increasing)) } } diff --git a/datafusion/physical-expr/src/scalar_function.rs b/datafusion/physical-expr/src/scalar_function.rs index 62a09271f9c0..383e7ace70d0 100644 --- a/datafusion/physical-expr/src/scalar_function.rs +++ b/datafusion/physical-expr/src/scalar_function.rs @@ -251,12 +251,23 @@ pub fn out_ordering( func: &FuncMonotonicity, arg_orderings: &[SortProperties], ) -> SortProperties { - let monotonicity_vec: Vec> = func.into(); - - monotonicity_vec.iter().zip(arg_orderings).fold( + arg_orderings.iter().enumerate().fold( SortProperties::Singleton, - |prev_sort, (item, arg)| { - let current_sort = func_order_in_one_dimension(item, arg); + |prev_sort, (index, arg)| { + let arg_monotonicity: Option = match func { + FuncMonotonicity::None => None, + FuncMonotonicity::Increasing => Some(true), + FuncMonotonicity::Decreasing => Some(false), + FuncMonotonicity::Mixed(inner_vec) => { + if inner_vec.len() > index { + inner_vec[index] + } else { + None + } + } + }; + + let current_sort = func_order_in_one_dimension(&arg_monotonicity, arg); match (prev_sort, current_sort) { (_, SortProperties::Unordered) => SortProperties::Unordered, @@ -301,3 +312,39 @@ fn func_order_in_one_dimension( } } } + +#[cfg(test)] +mod tests { + use arrow_schema::Schema; + + use datafusion_common::{DFSchema, Result}; + use datafusion_expr::{FuncMonotonicity, ScalarUDF}; + + use crate::utils::tests::TestScalarUDF; + use crate::ScalarFunctionExpr; + + use super::create_physical_expr; + + #[test] + fn test_function_expr() -> Result<()> { + let udf = ScalarUDF::from(TestScalarUDF::new()); + + let e = crate::expressions::lit(1.1); + let p_expr = + create_physical_expr(&udf, &[e], &Schema::empty(), &[], &DFSchema::empty())?; + let expr_monotonicity = p_expr + .as_any() + .downcast_ref::() + .unwrap() + .monotonicity(); + + assert_eq!(expr_monotonicity, &Some(FuncMonotonicity::Increasing)); + + assert!(expr_monotonicity + .as_ref() + .unwrap() + .matches(&FuncMonotonicity::Mixed(vec![Some(true)]))); + + Ok(()) + } +} diff --git a/datafusion/physical-expr/src/utils/mod.rs b/datafusion/physical-expr/src/utils/mod.rs index f72ff82d90e9..c2f884b5fad7 100644 --- a/datafusion/physical-expr/src/utils/mod.rs +++ b/datafusion/physical-expr/src/utils/mod.rs @@ -310,7 +310,7 @@ pub(crate) mod tests { } fn monotonicity(&self) -> Result> { - Ok(Some(FuncMonotonicity::new_increasing())) + Ok(Some(FuncMonotonicity::Increasing)) } fn invoke(&self, args: &[ColumnarValue]) -> Result { From e5f72bbb2429d53c85e6ba2b827830b892921150 Mon Sep 17 00:00:00 2001 From: Kunal Kundu Date: Thu, 9 May 2024 20:34:20 +0530 Subject: [PATCH 7/7] fix clippy nit --- datafusion/expr/src/signature.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/expr/src/signature.rs b/datafusion/expr/src/signature.rs index c3d53e94501f..e3dcc4d99bc2 100644 --- a/datafusion/expr/src/signature.rs +++ b/datafusion/expr/src/signature.rs @@ -386,7 +386,7 @@ impl FuncMonotonicity { match (self, other) { (FuncMonotonicity::None, FuncMonotonicity::Mixed(inner_vec)) | (FuncMonotonicity::Mixed(inner_vec), FuncMonotonicity::None) => { - inner_vec.iter().all(|&x| x == None) + inner_vec.iter().all(|&x| x.is_none()) } (FuncMonotonicity::Increasing, FuncMonotonicity::Mixed(inner_vec)) | (FuncMonotonicity::Mixed(inner_vec), FuncMonotonicity::Increasing) => {