diff --git a/datafusion/expr/src/udf.rs b/datafusion/expr/src/udf.rs index d623d3541fc7..8ec5c50766c4 100644 --- a/datafusion/expr/src/udf.rs +++ b/datafusion/expr/src/udf.rs @@ -205,10 +205,6 @@ impl ScalarUDF { pub fn short_circuits(&self) -> bool { self.inner.short_circuits() } - - pub fn support_randomness(&self) -> bool { - self.inner.support_randomness() - } } impl From for ScalarUDF @@ -348,7 +344,15 @@ pub trait ScalarUDFImpl: Debug + Send + Sync { ) } - /// Invoke the function without `args` but number of rows, returning the appropriate result + /// Invoke the function without `args` but number of rows, returning the + /// appropriate result + /// + /// Note this is different than [`Self::invoke`] in that it is called with + /// the number of rows in the batch. + /// + /// For functions that return a constant such as `pi()` the number of rows + /// does not matter. However for functions such as `random()` that return a + /// batch with different values for each row, the number of rows is needed. fn invoke_no_args(&self, _number_rows: usize) -> Result { not_impl_err!( "Function {} does not implement invoke_no_args but called", @@ -407,12 +411,6 @@ pub trait ScalarUDFImpl: Debug + Send + Sync { fn short_circuits(&self) -> bool { false } - - /// Returns true if the function supports randomness, This is useful for functions that need to generate - /// random values for each row. `invoke_no_args` can be called in this case. - fn support_randomness(&self) -> bool { - false - } } /// ScalarUDF that adds an alias to the underlying function. It is better to diff --git a/datafusion/functions-array/src/make_array.rs b/datafusion/functions-array/src/make_array.rs index 0439a736ee42..c8e30c9df574 100644 --- a/datafusion/functions-array/src/make_array.rs +++ b/datafusion/functions-array/src/make_array.rs @@ -104,6 +104,10 @@ impl ScalarUDFImpl for MakeArray { make_scalar_function(make_array_inner)(args) } + fn invoke_no_args(&self, _num_rows: usize) -> Result { + self.invoke(&[]) + } + fn aliases(&self) -> &[String] { &self.aliases } diff --git a/datafusion/functions/src/math/pi.rs b/datafusion/functions/src/math/pi.rs index c135a13f1256..108efdf92975 100644 --- a/datafusion/functions/src/math/pi.rs +++ b/datafusion/functions/src/math/pi.rs @@ -66,6 +66,10 @@ impl ScalarUDFImpl for PiFunc { )))) } + fn invoke_no_args(&self, _number_rows: usize) -> Result { + self.invoke(&[]) + } + fn monotonicity(&self) -> Result> { Ok(Some(vec![Some(true)])) } diff --git a/datafusion/functions/src/math/random.rs b/datafusion/functions/src/math/random.rs index 8a993541eee3..4f6650fb9539 100644 --- a/datafusion/functions/src/math/random.rs +++ b/datafusion/functions/src/math/random.rs @@ -63,11 +63,8 @@ impl ScalarUDFImpl for RandomFunc { Ok(Float64) } - fn support_randomness(&self) -> bool { - true - } - fn invoke_no_args(&self, num_rows: usize) -> Result { + // Since random is volatile, return a different value each row let mut rng = thread_rng(); let values = std::iter::repeat_with(|| rng.gen_range(0.0..1.0)).take(num_rows); let array = Float64Array::from_iter_values(values); diff --git a/datafusion/functions/src/string/uuid.rs b/datafusion/functions/src/string/uuid.rs index 707ac8130fff..869e1629ad94 100644 --- a/datafusion/functions/src/string/uuid.rs +++ b/datafusion/functions/src/string/uuid.rs @@ -57,10 +57,6 @@ impl ScalarUDFImpl for UuidFunc { Ok(Utf8) } - fn support_randomness(&self) -> bool { - true - } - /// Prints random (v4) uuid values per row /// uuid() = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11' fn invoke_no_args(&self, num_rows: usize) -> Result { diff --git a/datafusion/physical-expr/src/scalar_function.rs b/datafusion/physical-expr/src/scalar_function.rs index a16a00103f9d..f592fdc44996 100644 --- a/datafusion/physical-expr/src/scalar_function.rs +++ b/datafusion/physical-expr/src/scalar_function.rs @@ -146,7 +146,7 @@ impl PhysicalExpr for ScalarFunctionExpr { // evaluate the function match self.fun { ScalarFunctionDefinition::UDF(ref fun) => { - if fun.support_randomness() { + if inputs.is_empty() { fun.invoke_no_args(batch.num_rows()) } else { fun.invoke(&inputs)