Skip to content

Commit 739364b

Browse files
Add custom nullability to SparkMakeInterval
- Implement return_field_from_args for SparkMakeInterval - With no arguments: returns non-nullable (always zero interval) - With arguments: returns nullable (input nulls or overflow possible) Closes #19155
1 parent 9a9ff8d commit 739364b

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

datafusion/spark/src/function/datetime/make_interval.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ use std::sync::Arc;
2121
use arrow::array::{Array, ArrayRef, IntervalMonthDayNanoBuilder, PrimitiveArray};
2222
use arrow::datatypes::DataType::Interval;
2323
use arrow::datatypes::IntervalUnit::MonthDayNano;
24-
use arrow::datatypes::{DataType, IntervalMonthDayNano};
24+
use arrow::datatypes::{DataType, Field, FieldRef, IntervalMonthDayNano};
2525
use datafusion_common::types::{NativeType, logical_float64, logical_int32};
2626
use datafusion_common::{DataFusionError, Result, ScalarValue, plan_datafusion_err};
2727
use datafusion_expr::{
28-
Coercion, ColumnarValue, ScalarFunctionArgs, ScalarUDFImpl, Signature, TypeSignature,
29-
TypeSignatureClass, Volatility,
28+
Coercion, ColumnarValue, ReturnFieldArgs, ScalarFunctionArgs, ScalarUDFImpl, Signature,
29+
TypeSignature, TypeSignatureClass, Volatility,
3030
};
3131
use datafusion_functions::utils::make_scalar_function;
3232

@@ -122,6 +122,31 @@ impl ScalarUDFImpl for SparkMakeInterval {
122122
Ok(Interval(MonthDayNano))
123123
}
124124

125+
fn return_field_from_args(&self, args: ReturnFieldArgs<'_>) -> Result<FieldRef> {
126+
// Spark make_interval semantics:
127+
// - Returns NULL if ANY input argument is NULL
128+
// - Returns NULL on arithmetic overflow (e.g., year * 12 + month overflows)
129+
// - With no arguments, returns a non-null zero interval
130+
//
131+
// Therefore:
132+
// - If no arguments: not nullable (always returns 0 interval)
133+
// - If any arguments: nullable (inputs might be null OR overflow might occur)
134+
let nullable = if args.arg_fields.is_empty() {
135+
false
136+
} else {
137+
// Always nullable when we have arguments because:
138+
// 1. Any nullable input → nullable output
139+
// 2. Overflow can occur even with non-null inputs → nullable output
140+
true
141+
};
142+
143+
Ok(Arc::new(Field::new(
144+
"make_interval",
145+
Interval(MonthDayNano),
146+
nullable,
147+
)))
148+
}
149+
125150
fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
126151
if args.args.is_empty() {
127152
return Ok(ColumnarValue::Scalar(ScalarValue::IntervalMonthDayNano(

0 commit comments

Comments
 (0)