Skip to content

Commit d412f43

Browse files
committed
Keep UDF source spans out of expression identity
1 parent 5654173 commit d412f43

1 file changed

Lines changed: 86 additions & 1 deletion

File tree

‎datafusion/expr/src/expr.rs‎

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,7 @@ impl Between {
945945
/// Invoke a [`ScalarUDF`] with a set of arguments
946946
///
947947
/// [`ScalarUDF`]: crate::ScalarUDF
948-
#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
948+
#[derive(Clone)]
949949
pub struct ScalarFunction {
950950
/// The function
951951
pub func: Arc<crate::ScalarUDF>,
@@ -955,6 +955,36 @@ pub struct ScalarFunction {
955955
pub spans: Spans,
956956
}
957957

958+
impl PartialEq for ScalarFunction {
959+
fn eq(&self, other: &Self) -> bool {
960+
self.func == other.func && self.args == other.args
961+
}
962+
}
963+
964+
impl Eq for ScalarFunction {}
965+
966+
impl PartialOrd for ScalarFunction {
967+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
968+
(&self.func, &self.args).partial_cmp(&(&other.func, &other.args))
969+
}
970+
}
971+
972+
impl Hash for ScalarFunction {
973+
fn hash<H: Hasher>(&self, state: &mut H) {
974+
self.func.hash(state);
975+
self.args.hash(state);
976+
}
977+
}
978+
979+
impl fmt::Debug for ScalarFunction {
980+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
981+
f.debug_struct("ScalarFunction")
982+
.field("func", &self.func)
983+
.field("args", &self.args)
984+
.finish()
985+
}
986+
}
987+
958988
impl ScalarFunction {
959989
// return the Function's name
960990
pub fn name(&self) -> &str {
@@ -4603,6 +4633,61 @@ mod test {
46034633
}
46044634
}
46054635

4636+
#[test]
4637+
fn scalar_function_source_spans_do_not_change_identity() {
4638+
use datafusion_common::{Location, Span};
4639+
use std::collections::hash_map::DefaultHasher;
4640+
4641+
#[derive(Debug, PartialEq, Eq, Hash)]
4642+
struct TestUdf {
4643+
signature: Signature,
4644+
}
4645+
4646+
impl ScalarUDFImpl for TestUdf {
4647+
fn name(&self) -> &str {
4648+
"test_scalar_udf"
4649+
}
4650+
4651+
fn signature(&self) -> &Signature {
4652+
&self.signature
4653+
}
4654+
4655+
fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
4656+
Ok(DataType::Int32)
4657+
}
4658+
4659+
fn invoke_with_args(
4660+
&self,
4661+
_args: ScalarFunctionArgs,
4662+
) -> Result<ColumnarValue> {
4663+
unimplemented!()
4664+
}
4665+
}
4666+
4667+
let udf = Arc::new(ScalarUDF::new_from_impl(TestUdf {
4668+
signature: Signature::exact(vec![DataType::Int32], Volatility::Immutable),
4669+
}));
4670+
let plain = ScalarFunction::new_udf(Arc::clone(&udf), vec![lit(1)]);
4671+
let mut located = ScalarFunction::new_udf(udf, vec![lit(1)]);
4672+
located.spans.add_span(Span::new(
4673+
Location { line: 1, column: 8 },
4674+
Location {
4675+
line: 1,
4676+
column: 23,
4677+
},
4678+
));
4679+
4680+
assert_eq!(plain, located);
4681+
assert_eq!(plain.partial_cmp(&located), Some(Ordering::Equal));
4682+
assert_eq!(format!("{plain:?}"), format!("{located:?}"));
4683+
let hash = |function: &ScalarFunction| {
4684+
let mut hasher = DefaultHasher::new();
4685+
function.hash(&mut hasher);
4686+
hasher.finish()
4687+
};
4688+
assert_eq!(hash(&plain), hash(&located));
4689+
}
4690+
46064691
mod intersect_metadata_tests {
46074692
use super::super::intersect_metadata_for_union;
46084693
use std::collections::HashMap;

0 commit comments

Comments
 (0)