@@ -34,49 +34,42 @@ use std::{
34
34
///
35
35
/// See the documetnation on [`PartitionEvaluator`] for more details
36
36
///
37
+ /// 1. For simple (less performant) use cases, use [`create_udwf`] and [`simple_udwf.rs`].
38
+ ///
39
+ /// 2. For advanced use cases, use [`WindowUDFImpl`] and [`advanced_udf.rs`].
40
+ ///
41
+ /// # API Note
42
+ /// This is a separate struct from `WindowUDFImpl` to maintain backwards
43
+ /// compatibility with the older API.
44
+ ///
37
45
/// [`PartitionEvaluator`]: crate::PartitionEvaluator
38
- #[ derive( Clone ) ]
46
+ /// [`create_udwf`]: crate::expr_fn::create_udwf
47
+ /// [`simple_udwf.rs`]: https://github.com/apache/arrow-datafusion/blob/main/datafusion-examples/examples/simple_udwf.rs
48
+ /// [`advanced_udwf.rs`]: https://github.com/apache/arrow-datafusion/blob/main/datafusion-examples/examples/advanced_udwf.rs
49
+ #[ derive( Debug , Clone ) ]
39
50
pub struct WindowUDF {
40
- /// name
41
- name : String ,
42
- /// signature
43
- signature : Signature ,
44
- /// Return type
45
- return_type : ReturnTypeFunction ,
46
- /// Return the partition evaluator
47
- partition_evaluator_factory : PartitionEvaluatorFactory ,
48
- }
49
-
50
- impl Debug for WindowUDF {
51
- fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
52
- f. debug_struct ( "WindowUDF" )
53
- . field ( "name" , & self . name )
54
- . field ( "signature" , & self . signature )
55
- . field ( "return_type" , & "<func>" )
56
- . field ( "partition_evaluator_factory" , & "<func>" )
57
- . finish_non_exhaustive ( )
58
- }
51
+ inner : Arc < dyn WindowUDFImpl > ,
59
52
}
60
53
61
54
/// Defines how the WindowUDF is shown to users
62
55
impl Display for WindowUDF {
63
56
fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
64
- write ! ( f, "{}" , self . name)
57
+ write ! ( f, "{}" , self . name( ) )
65
58
}
66
59
}
67
60
68
61
impl PartialEq for WindowUDF {
69
62
fn eq ( & self , other : & Self ) -> bool {
70
- self . name == other. name && self . signature == other. signature
63
+ self . name ( ) == other. name ( ) && self . signature ( ) == other. signature ( )
71
64
}
72
65
}
73
66
74
67
impl Eq for WindowUDF { }
75
68
76
69
impl std:: hash:: Hash for WindowUDF {
77
70
fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
78
- self . name . hash ( state) ;
79
- self . signature . hash ( state) ;
71
+ self . name ( ) . hash ( state) ;
72
+ self . signature ( ) . hash ( state) ;
80
73
}
81
74
}
82
75
@@ -92,40 +85,31 @@ impl WindowUDF {
92
85
return_type : & ReturnTypeFunction ,
93
86
partition_evaluator_factory : & PartitionEvaluatorFactory ,
94
87
) -> Self {
95
- Self {
96
- name : name. to_string ( ) ,
88
+ Self :: new_from_impl ( WindowUDFLegacyWrapper {
89
+ name : name. to_owned ( ) ,
97
90
signature : signature. clone ( ) ,
98
91
return_type : return_type. clone ( ) ,
99
92
partition_evaluator_factory : partition_evaluator_factory. clone ( ) ,
100
- }
93
+ } )
101
94
}
102
95
103
96
/// Create a new `WindowUDF` from a `[WindowUDFImpl]` trait object
104
97
///
105
98
/// Note this is the same as using the `From` impl (`WindowUDF::from`)
106
99
pub fn new_from_impl < F > ( fun : F ) -> WindowUDF
107
100
where
108
- F : WindowUDFImpl + Send + Sync + ' static ,
101
+ F : WindowUDFImpl + ' static ,
109
102
{
110
- let arc_fun = Arc :: new ( fun) ;
111
- let captured_self = arc_fun. clone ( ) ;
112
- let return_type: ReturnTypeFunction = Arc :: new ( move |arg_types| {
113
- let return_type = captured_self. return_type ( arg_types) ?;
114
- Ok ( Arc :: new ( return_type) )
115
- } ) ;
116
-
117
- let captured_self = arc_fun. clone ( ) ;
118
- let partition_evaluator_factory: PartitionEvaluatorFactory =
119
- Arc :: new ( move || captured_self. partition_evaluator ( ) ) ;
120
-
121
103
Self {
122
- name : arc_fun. name ( ) . to_string ( ) ,
123
- signature : arc_fun. signature ( ) . clone ( ) ,
124
- return_type : return_type. clone ( ) ,
125
- partition_evaluator_factory,
104
+ inner : Arc :: new ( fun) ,
126
105
}
127
106
}
128
107
108
+ /// Return the underlying [`WindowUDFImpl`] trait object for this function
109
+ pub fn inner ( & self ) -> Arc < dyn WindowUDFImpl > {
110
+ self . inner . clone ( )
111
+ }
112
+
129
113
/// creates a [`Expr`] that calls the window function given
130
114
/// the `partition_by`, `order_by`, and `window_frame` definition
131
115
///
@@ -150,25 +134,29 @@ impl WindowUDF {
150
134
}
151
135
152
136
/// Returns this function's name
137
+ ///
138
+ /// See [`WindowUDFImpl::name`] for more details.
153
139
pub fn name ( & self ) -> & str {
154
- & self . name
140
+ self . inner . name ( )
155
141
}
156
142
157
143
/// Returns this function's signature (what input types are accepted)
144
+ ///
145
+ /// See [`WindowUDFImpl::signature`] for more details.
158
146
pub fn signature ( & self ) -> & Signature {
159
- & self . signature
147
+ self . inner . signature ( )
160
148
}
161
149
162
150
/// Return the type of the function given its input types
151
+ ///
152
+ /// See [`WindowUDFImpl::return_type`] for more details.
163
153
pub fn return_type ( & self , args : & [ DataType ] ) -> Result < DataType > {
164
- // Old API returns an Arc of the datatype for some reason
165
- let res = ( self . return_type ) ( args) ?;
166
- Ok ( res. as_ref ( ) . clone ( ) )
154
+ self . inner . return_type ( args)
167
155
}
168
156
169
157
/// Return a `PartitionEvaluator` for evaluating this window function
170
158
pub fn partition_evaluator_factory ( & self ) -> Result < Box < dyn PartitionEvaluator > > {
171
- ( self . partition_evaluator_factory ) ( )
159
+ self . inner . partition_evaluator ( )
172
160
}
173
161
}
174
162
@@ -198,6 +186,7 @@ where
198
186
/// # use datafusion_common::{DataFusionError, plan_err, Result};
199
187
/// # use datafusion_expr::{col, Signature, Volatility, PartitionEvaluator, WindowFrame};
200
188
/// # use datafusion_expr::{WindowUDFImpl, WindowUDF};
189
+ /// #[derive(Debug, Clone)]
201
190
/// struct SmoothIt {
202
191
/// signature: Signature
203
192
/// };
@@ -236,7 +225,7 @@ where
236
225
/// WindowFrame::new(false),
237
226
/// );
238
227
/// ```
239
- pub trait WindowUDFImpl {
228
+ pub trait WindowUDFImpl : Debug + Send + Sync {
240
229
/// Returns this object as an [`Any`] trait object
241
230
fn as_any ( & self ) -> & dyn Any ;
242
231
@@ -254,3 +243,52 @@ pub trait WindowUDFImpl {
254
243
/// Invoke the function, returning the [`PartitionEvaluator`] instance
255
244
fn partition_evaluator ( & self ) -> Result < Box < dyn PartitionEvaluator > > ;
256
245
}
246
+
247
+ /// Implementation of [`WindowUDFImpl`] that wraps the function style pointers
248
+ /// of the older API (see <https://github.com/apache/arrow-datafusion/pull/8719>
249
+ /// for more details)
250
+ pub struct WindowUDFLegacyWrapper {
251
+ /// name
252
+ name : String ,
253
+ /// signature
254
+ signature : Signature ,
255
+ /// Return type
256
+ return_type : ReturnTypeFunction ,
257
+ /// Return the partition evaluator
258
+ partition_evaluator_factory : PartitionEvaluatorFactory ,
259
+ }
260
+
261
+ impl Debug for WindowUDFLegacyWrapper {
262
+ fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
263
+ f. debug_struct ( "WindowUDF" )
264
+ . field ( "name" , & self . name )
265
+ . field ( "signature" , & self . signature )
266
+ . field ( "return_type" , & "<func>" )
267
+ . field ( "partition_evaluator_factory" , & "<func>" )
268
+ . finish_non_exhaustive ( )
269
+ }
270
+ }
271
+
272
+ impl WindowUDFImpl for WindowUDFLegacyWrapper {
273
+ fn as_any ( & self ) -> & dyn Any {
274
+ self
275
+ }
276
+
277
+ fn name ( & self ) -> & str {
278
+ & self . name
279
+ }
280
+
281
+ fn signature ( & self ) -> & Signature {
282
+ & self . signature
283
+ }
284
+
285
+ fn return_type ( & self , arg_types : & [ DataType ] ) -> Result < DataType > {
286
+ // Old API returns an Arc of the datatype for some reason
287
+ let res = ( self . return_type ) ( arg_types) ?;
288
+ Ok ( res. as_ref ( ) . clone ( ) )
289
+ }
290
+
291
+ fn partition_evaluator ( & self ) -> Result < Box < dyn PartitionEvaluator > > {
292
+ ( self . partition_evaluator_factory ) ( )
293
+ }
294
+ }
0 commit comments