Skip to content

Commit 2aad9d2

Browse files
authored
functions: Remove NullHandling from scalar funcs (#14531)
3dfce7d added an enum to all scalar functions called `NullHandling`, with two variants: `PassThrough` and Propagate`. `PassThrough` would pass through null inputs to the function implementation. `Propagate` would cause the function to return null if any of the inputs were scalar and null, it would not do anything if an input was an array and null. Function implementors were responsible for handling null array inputs and making sure the behavior was consistent with the scalar null behavior caused by `NullHandling`. If the function signature correctly described the accepted types, then the null array input handling would also work for null scalar inputs. However, if the function signature was `VariadicAny`, then the null array input handling would not work for null scalar inputs. The reason is that when the signature is `VariadicAny`, null inputs are not properly typed (for example `ScalarValue::Null` instead of `ScalarValue::Int64(None)`. So it turns out that `NullHandling` was only useful for compensating for non-descriptive function signatures. Furthermore, many array functions use a signature of `VariadicAny` and reject invalid types within the function implementation. This does not work with `NullHandling::Propagate`, because any null input would skip the function implementation, which would skip the type validation. So, if a function wanted to use `NullHandling::Propagate`, then they would need to use a descriptive function signature. However, using a descriptive function signature removes the usefulness of `NullHandling::Propagate`. So as it turns out `NullHandling::Propagate` is never useful. For all the reasons stated above, this commit removes the `NullHandling` enum.
1 parent 46bcb03 commit 2aad9d2

4 files changed

Lines changed: 4 additions & 45 deletions

File tree

datafusion/expr/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ pub use udaf::{
9595
SetMonotonicity, StatisticsArgs,
9696
};
9797
pub use udf::{
98-
scalar_doc_sections, NullHandling, ReturnInfo, ReturnTypeArgs, ScalarFunctionArgs,
99-
ScalarUDF, ScalarUDFImpl,
98+
scalar_doc_sections, ReturnInfo, ReturnTypeArgs, ScalarFunctionArgs, ScalarUDF,
99+
ScalarUDFImpl,
100100
};
101101
pub use udwf::{window_doc_sections, ReversedUDWF, WindowUDF, WindowUDFImpl};
102102
pub use window_frame::{WindowFrame, WindowFrameBound, WindowFrameUnits};

datafusion/expr/src/udf.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,6 @@ impl ScalarUDF {
200200
self.inner.return_type_from_args(args)
201201
}
202202

203-
/// Returns the behavior that this function has when any of the inputs are Null.
204-
pub fn null_handling(&self) -> NullHandling {
205-
self.inner.null_handling()
206-
}
207-
208203
/// Do the function rewrite
209204
///
210205
/// See [`ScalarUDFImpl::simplify`] for more details.
@@ -422,15 +417,6 @@ impl ReturnInfo {
422417
}
423418
}
424419

425-
/// A function's behavior when the input is Null.
426-
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
427-
pub enum NullHandling {
428-
/// Null inputs are passed into the function implementation.
429-
PassThrough,
430-
/// Any Null input causes the function to return Null.
431-
Propagate,
432-
}
433-
434420
/// Trait for implementing user defined scalar functions.
435421
///
436422
/// This trait exposes the full API for implementing user defined functions and
@@ -603,11 +589,6 @@ pub trait ScalarUDFImpl: Debug + Send + Sync {
603589
true
604590
}
605591

606-
/// Returns the behavior that this function has when any of the inputs are Null.
607-
fn null_handling(&self) -> NullHandling {
608-
NullHandling::PassThrough
609-
}
610-
611592
/// Invoke the function on `args`, returning the appropriate result
612593
///
613594
/// Note: This method is deprecated and will be removed in future releases.

datafusion/functions-nested/src/extract.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use datafusion_common::{
3333
};
3434
use datafusion_expr::{ArrayFunctionSignature, Expr, TypeSignature};
3535
use datafusion_expr::{
36-
ColumnarValue, Documentation, NullHandling, ScalarUDFImpl, Signature, Volatility,
36+
ColumnarValue, Documentation, ScalarUDFImpl, Signature, Volatility,
3737
};
3838
use datafusion_macros::user_doc;
3939
use std::any::Any;
@@ -385,10 +385,6 @@ impl ScalarUDFImpl for ArraySlice {
385385
Ok(arg_types[0].clone())
386386
}
387387

388-
fn null_handling(&self) -> NullHandling {
389-
NullHandling::Propagate
390-
}
391-
392388
fn invoke_batch(
393389
&self,
394390
args: &[ColumnarValue],
@@ -690,10 +686,6 @@ impl ScalarUDFImpl for ArrayPopFront {
690686
Ok(arg_types[0].clone())
691687
}
692688

693-
fn null_handling(&self) -> NullHandling {
694-
NullHandling::Propagate
695-
}
696-
697689
fn invoke_batch(
698690
&self,
699691
args: &[ColumnarValue],
@@ -794,10 +786,6 @@ impl ScalarUDFImpl for ArrayPopBack {
794786
Ok(arg_types[0].clone())
795787
}
796788

797-
fn null_handling(&self) -> NullHandling {
798-
NullHandling::Propagate
799-
}
800-
801789
fn invoke_batch(
802790
&self,
803791
args: &[ColumnarValue],

datafusion/physical-expr/src/scalar_function.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ use datafusion_expr::interval_arithmetic::Interval;
4545
use datafusion_expr::sort_properties::ExprProperties;
4646
use datafusion_expr::type_coercion::functions::data_types_with_scalar_udf;
4747
use datafusion_expr::{
48-
expr_vec_fmt, ColumnarValue, Expr, NullHandling, ReturnTypeArgs, ScalarFunctionArgs,
49-
ScalarUDF,
48+
expr_vec_fmt, ColumnarValue, Expr, ReturnTypeArgs, ScalarFunctionArgs, ScalarUDF,
5049
};
5150

5251
/// Physical expression of a scalar function
@@ -187,15 +186,6 @@ impl PhysicalExpr for ScalarFunctionExpr {
187186
.map(|e| e.evaluate(batch))
188187
.collect::<Result<Vec<_>>>()?;
189188

190-
if self.fun.null_handling() == NullHandling::Propagate
191-
&& args.iter().any(
192-
|arg| matches!(arg, ColumnarValue::Scalar(scalar) if scalar.is_null()),
193-
)
194-
{
195-
let null_value = ScalarValue::try_from(&self.return_type)?;
196-
return Ok(ColumnarValue::Scalar(null_value));
197-
}
198-
199189
let input_empty = args.is_empty();
200190
let input_all_scalar = args
201191
.iter()

0 commit comments

Comments
 (0)