@@ -945,12 +945,44 @@ 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 > ,
952952 /// List of expressions to feed to the functions as arguments
953953 pub args : Vec < Expr > ,
954+ /// SQL source locations of this invocation, if known.
955+ pub spans : Spans ,
956+ }
957+
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+ }
954986}
955987
956988impl ScalarFunction {
@@ -965,7 +997,11 @@ impl ScalarFunction {
965997 ///
966998 /// [`ScalarUDF`]: crate::ScalarUDF
967999 pub fn new_udf ( udf : Arc < crate :: ScalarUDF > , args : Vec < Expr > ) -> Self {
968- Self { func : udf, args }
1000+ Self {
1001+ func : udf,
1002+ args,
1003+ spans : Spans :: new ( ) ,
1004+ }
9691005 }
9701006}
9711007
@@ -2304,6 +2340,7 @@ impl Expr {
23042340 pub fn spans ( & self ) -> Option < & Spans > {
23052341 match self {
23062342 Expr :: Column ( col) => Some ( & col. spans ) ,
2343+ Expr :: ScalarFunction ( function) => Some ( & function. spans ) ,
23072344 Expr :: Not ( inner) | Expr :: Negative ( inner) => inner. spans ( ) ,
23082345 _ => None ,
23092346 }
@@ -2508,10 +2545,12 @@ impl NormalizeEq for Expr {
25082545 Expr :: ScalarFunction ( ScalarFunction {
25092546 func : self_func,
25102547 args : self_args,
2548+ ..
25112549 } ) ,
25122550 Expr :: ScalarFunction ( ScalarFunction {
25132551 func : other_func,
25142552 args : other_args,
2553+ ..
25152554 } ) ,
25162555 ) => {
25172556 self_func. name ( ) == other_func. name ( )
@@ -2823,7 +2862,9 @@ impl HashNode for Expr {
28232862 | Expr :: TryCast ( TryCast { expr : _expr, field } ) => {
28242863 field. hash ( state) ;
28252864 }
2826- Expr :: ScalarFunction ( ScalarFunction { func, args : _args } ) => {
2865+ Expr :: ScalarFunction ( ScalarFunction {
2866+ func, args : _args, ..
2867+ } ) => {
28272868 func. hash ( state) ;
28282869 }
28292870 Expr :: AggregateFunction ( AggregateFunction {
@@ -3158,7 +3199,7 @@ impl Display for SchemaDisplay<'_> {
31583199 let name = if * outer { "UNNEST_OUTER" } else { "UNNEST" } ;
31593200 write ! ( f, "{name}({})" , SchemaDisplay ( expr) )
31603201 }
3161- Expr :: ScalarFunction ( ScalarFunction { func, args } ) => {
3202+ Expr :: ScalarFunction ( ScalarFunction { func, args, .. } ) => {
31623203 match func. schema_name ( args) {
31633204 Ok ( name) => {
31643205 write ! ( f, "{name}" )
@@ -4555,6 +4596,7 @@ mod test {
45554596 let udf = Expr :: ScalarFunction ( ScalarFunction {
45564597 func : Arc :: new ( ScalarUDF :: new_from_impl ( TestUDF { } ) ) ,
45574598 args : vec ! [ expr( ) , expr( ) ] ,
4599+ spans : Spans :: new ( ) ,
45584600 } ) ;
45594601 let Expr :: ScalarFunction ( scalar) = & udf else {
45604602 unreachable ! ( )
@@ -4591,6 +4633,61 @@ mod test {
45914633 }
45924634 }
45934635
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+
45944691 mod intersect_metadata_tests {
45954692 use super :: super :: intersect_metadata_for_union;
45964693 use std:: collections:: HashMap ;
0 commit comments