@@ -248,158 +248,100 @@ pub fn check_function_length_with_diag(
248
248
if current_types. is_empty ( ) {
249
249
if signature. supports_zero_argument ( ) {
250
250
return Ok ( ( ) ) ;
251
- } else if signature. used_to_support_zero_arguments ( ) {
252
- // Special error to help during upgrade
253
- let base_error = plan_datafusion_err ! (
254
- "'{}' does not support zero arguments. Use TypeSignature::Nullary for zero arguments" ,
255
- function_name
256
- ) ;
257
- let mut diagnostic = Diagnostic :: new_error (
258
- format ! ( "Zero arguments not supported for {} function" , function_name) ,
259
- function_call_site,
260
- ) ;
261
- diagnostic. add_help (
262
- "Use TypeSignature::Nullary for functions that take no arguments" ,
263
- None ,
264
- ) ;
265
- return Err ( base_error. with_diagnostic ( diagnostic) ) ;
251
+ }
252
+
253
+ let ( error_message, note) = if signature. used_to_support_zero_arguments ( ) {
254
+ (
255
+ format ! ( "Zero arguments not supported for {} function. Use TypeSignature::Nullary for zero arguments" , function_name) ,
256
+ "Use TypeSignature::Nullary for functions that take no arguments" . to_string ( )
257
+ )
266
258
} else {
267
- let base_error = plan_datafusion_err ! (
268
- "'{}' does not support zero arguments" ,
269
- function_name
270
- ) ;
271
- let mut diagnostic = Diagnostic :: new_error (
259
+ (
272
260
format ! ( "Zero arguments not supported for {} function" , function_name) ,
273
- function_call_site ,
274
- ) ;
275
- diagnostic . add_note (
276
- format ! ( "Function {} requires at least one argument" , function_name ) ,
277
- None ,
278
- ) ;
279
- return Err ( base_error . with_diagnostic ( diagnostic ) ) ;
280
- }
261
+ format ! ( "Function {} requires at least one argument" , function_name )
262
+ )
263
+ } ;
264
+
265
+ let mut diagnostic = Diagnostic :: new_error ( error_message . clone ( ) , function_call_site ) ;
266
+ diagnostic . add_note ( note , None ) ;
267
+
268
+ return Err ( plan_datafusion_err ! ( "{}" , error_message ) . with_diagnostic ( diagnostic ) ) ;
281
269
}
282
270
283
271
// Helper closure to create and return an error with diagnostic information
284
272
let create_error = |expected : & str , got : usize | {
285
- let base_error = plan_datafusion_err ! (
273
+ let error_message = format ! (
286
274
"Function '{}' {}, got {}" ,
287
275
function_name,
288
276
expected,
289
- got
277
+ got,
290
278
) ;
291
279
292
- let mut diagnostic = Diagnostic :: new_error (
293
- format ! (
294
- "Wrong number of arguments for {} function call" ,
295
- function_name
296
- ) ,
297
- function_call_site,
298
- ) ;
299
- diagnostic. add_note (
300
- format ! (
301
- "Function {} {}, but {} {} provided" ,
302
- function_name,
303
- expected,
304
- got,
305
- if got == 1 { "was" } else { "were" }
306
- ) ,
307
- None ,
308
- ) ;
280
+ let diagnostic = Diagnostic :: new_error ( error_message. clone ( ) , function_call_site) ;
309
281
310
- Err ( base_error . with_diagnostic ( diagnostic) )
282
+ Err ( plan_datafusion_err ! ( "{}" , error_message ) . with_diagnostic ( diagnostic) )
311
283
} ;
312
284
313
285
match signature {
314
286
TypeSignature :: Uniform ( num, _) |
315
287
TypeSignature :: Numeric ( num) |
316
288
TypeSignature :: String ( num) |
317
289
TypeSignature :: Comparable ( num) |
318
- TypeSignature :: Any ( num) => {
319
- if current_types. len ( ) != * num {
320
- return create_error ( & format ! ( "expects {} arguments" , num) , current_types. len ( ) ) ;
321
- }
290
+ TypeSignature :: Any ( num) if current_types. len ( ) != * num => {
291
+ return create_error ( & format ! ( "expects {} arguments" , num) , current_types. len ( ) ) ;
322
292
} ,
323
- TypeSignature :: Exact ( types) => {
324
- if current_types. len ( ) != types. len ( ) {
325
- return create_error ( & format ! ( "expects {} arguments" , types. len( ) ) , current_types. len ( ) ) ;
326
- }
293
+ // Length-based signature types
294
+ TypeSignature :: Exact ( types) if current_types. len ( ) != types. len ( ) => {
295
+ return create_error ( & format ! ( "expects {} arguments" , types. len( ) ) , current_types. len ( ) ) ;
327
296
} ,
328
- TypeSignature :: Coercible ( types) => {
329
- if current_types. len ( ) != types. len ( ) {
330
- return create_error ( & format ! ( "expects {} arguments" , types. len( ) ) , current_types. len ( ) ) ;
331
- }
297
+ TypeSignature :: Coercible ( types) if current_types. len ( ) != types. len ( ) => {
298
+ return create_error ( & format ! ( "expects {} arguments" , types. len( ) ) , current_types. len ( ) ) ;
332
299
} ,
333
- TypeSignature :: Nullary => {
334
- if !current_types . is_empty ( ) {
335
- return create_error ( "expects zero arguments" , current_types. len ( ) ) ;
336
- }
300
+
301
+ // Zero argument signature type
302
+ TypeSignature :: Nullary if ! current_types. is_empty ( ) => {
303
+ return create_error ( "expects zero arguments" , current_types . len ( ) ) ;
337
304
} ,
338
- TypeSignature :: ArraySignature ( array_signature) => {
339
- match array_signature {
340
- ArrayFunctionSignature :: Array { arguments, .. } => {
341
- if current_types. len ( ) != arguments. len ( ) {
342
- return create_error ( & format ! ( "expects {} arguments" , arguments. len( ) ) , current_types. len ( ) ) ;
343
- }
344
- } ,
345
- ArrayFunctionSignature :: RecursiveArray => {
346
- if current_types. len ( ) != 1 {
347
- return create_error ( "expects exactly one array argument" , current_types. len ( ) ) ;
348
- }
349
- } ,
350
- ArrayFunctionSignature :: MapArray => {
351
- if current_types. len ( ) != 1 {
352
- return create_error ( "expects exactly one map argument" , current_types. len ( ) ) ;
353
- }
354
- } ,
355
- }
305
+
306
+ // Array signature types
307
+ TypeSignature :: ArraySignature ( array_signature) => match array_signature {
308
+ ArrayFunctionSignature :: Array { arguments, .. } if current_types. len ( ) != arguments. len ( ) => {
309
+ return create_error ( & format ! ( "expects {} arguments" , arguments. len( ) ) , current_types. len ( ) ) ;
310
+ } ,
311
+ ArrayFunctionSignature :: RecursiveArray | ArrayFunctionSignature :: MapArray if current_types. len ( ) != 1 => {
312
+ return create_error ( "expects exactly one array argument" , current_types. len ( ) ) ;
313
+ } ,
314
+ _ => { }
356
315
} ,
316
+
317
+ // Multiple signature type
357
318
TypeSignature :: OneOf ( signatures) => {
358
- // For OneOf, we'll consider it valid if it matches ANY of the signatures
359
- // We'll collect all errors to provide better diagnostics if nothing matches
360
- let mut all_errors = Vec :: new ( ) ;
361
-
319
+ // Try to match any signature
362
320
for sig in signatures {
363
- match check_function_length_with_diag ( function_name, sig, current_types, function_call_site) {
364
- Ok ( ( ) ) => return Ok ( ( ) ) , // If any signature matches, return immediately
365
- Err ( e) => all_errors. push ( e) ,
321
+ if check_function_length_with_diag ( function_name, sig, current_types, function_call_site) . is_ok ( ) {
322
+ return Ok ( ( ) ) ;
366
323
}
367
324
}
368
325
369
- // none of the signatures matched
370
- if !all_errors. is_empty ( ) {
371
-
372
- let base_error = plan_datafusion_err ! (
373
- "Function '{}' has no matching signature for {} arguments." ,
374
- function_name,
375
- current_types. len( )
376
- ) ;
377
-
378
- let mut diagnostic = Diagnostic :: new_error (
379
- format ! (
380
- "No matching signature for {} function with {} arguments" ,
381
- function_name,
382
- current_types. len( )
383
- ) ,
384
- function_call_site,
385
- ) ;
386
-
387
- diagnostic. add_note (
388
- format ! ( "The function {} has multiple possible signatures" , function_name) ,
389
- None ,
390
- ) ;
391
-
392
- return Err ( base_error. with_diagnostic ( diagnostic) ) ;
393
- }
326
+ // Create error for no matching signature
327
+ let error_message = format ! (
328
+ "Function '{}' has no matching signature for {} arguments" ,
329
+ function_name, current_types. len( )
330
+ ) ;
331
+
332
+ let mut diagnostic = Diagnostic :: new_error ( error_message. clone ( ) , function_call_site) ;
333
+ diagnostic. add_note (
334
+ format ! ( "The function {} has multiple possible signatures" , function_name) ,
335
+ None ,
336
+ ) ;
337
+
338
+ return Err ( plan_datafusion_err ! ( "{}" , error_message) . with_diagnostic ( diagnostic) ) ;
394
339
} ,
395
- // Signatures that accept variable numbers of arguments or are handled specially
396
- TypeSignature :: Variadic ( _) | TypeSignature :: VariadicAny | TypeSignature :: UserDefined => {
397
- // These cases are implicitly valid for any non-zero number of arguments:
398
- // - Variadic: accepts one or more arguments of specified types
399
- // - VariadicAny: accepts one or more arguments of any type
400
- // - UserDefined: custom validation handled by the UDF itself
401
- }
402
340
341
+ // All other cases:
342
+ // Variadic signatures: they are specifically designed for variable argument counts, so length checking isn't necessary.
343
+ // User-Defined signature: argument validation responsibility is delegated to the user-defined function implementation itself
344
+ _ => { }
403
345
}
404
346
405
347
Ok ( ( ) )
0 commit comments