use crate::function::signature;
use crate::{BuiltinScalarFunction, TypeSignature};
use arrow::datatypes::DataType;
impl TypeSignature {
fn to_string_repr(&self) -> Vec<String> {
match self {
TypeSignature::Variadic(types) => {
vec![format!("{}, ..", join_types(types, "/"))]
}
TypeSignature::Uniform(arg_count, valid_types) => {
vec![std::iter::repeat(join_types(valid_types, "/"))
.take(*arg_count)
.collect::<Vec<String>>()
.join(", ")]
}
TypeSignature::Exact(types) => {
vec![join_types(types, ", ")]
}
TypeSignature::Any(arg_count) => {
vec![std::iter::repeat("Any")
.take(*arg_count)
.collect::<Vec<&str>>()
.join(", ")]
}
TypeSignature::VariadicEqual => vec!["T, .., T".to_string()],
TypeSignature::VariadicAny => vec!["Any, .., Any".to_string()],
TypeSignature::OneOf(sigs) => {
sigs.iter().flat_map(|s| s.to_string_repr()).collect()
}
}
}
}
fn join_types<T: std::fmt::Display>(types: &[T], delimiter: &str) -> String {
types
.iter()
.map(|t| t.to_string())
.collect::<Vec<String>>()
.join(delimiter)
}
pub fn generate_signature_error_msg(
fun: &BuiltinScalarFunction,
input_expr_types: &[DataType],
) -> String {
let candidate_signatures = signature(fun)
.type_signature
.to_string_repr()
.iter()
.map(|args_str| format!("\t{}({})", fun, args_str))
.collect::<Vec<String>>()
.join("\n");
format!(
"No function matches the given name and argument types '{}({})'. You might need to add explicit type casts.\n\tCandidate functions:\n{}",
fun, join_types(input_expr_types, ", "), candidate_signatures
)
}