@@ -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 ) ]
949949pub 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+
958988impl 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