diff --git a/datafusion/expr/src/built_in_function.rs b/datafusion/expr/src/built_in_function.rs index e04106595876..7d0c662d2237 100644 --- a/datafusion/expr/src/built_in_function.rs +++ b/datafusion/expr/src/built_in_function.rs @@ -42,8 +42,6 @@ use strum_macros::EnumIter; #[derive(Debug, Clone, PartialEq, Eq, Hash, EnumIter, Copy)] pub enum BuiltinScalarFunction { // math functions - /// asin - Asin, /// atan Atan, /// atan2 @@ -360,7 +358,6 @@ impl BuiltinScalarFunction { pub fn volatility(&self) -> Volatility { match self { // Immutable scalar builtins - BuiltinScalarFunction::Asin => Volatility::Immutable, BuiltinScalarFunction::Atan => Volatility::Immutable, BuiltinScalarFunction::Atan2 => Volatility::Immutable, BuiltinScalarFunction::Acosh => Volatility::Immutable, @@ -870,8 +867,7 @@ impl BuiltinScalarFunction { utf8_to_int_type(&input_expr_types[0], "levenshtein") } - BuiltinScalarFunction::Asin - | BuiltinScalarFunction::Atan + BuiltinScalarFunction::Atan | BuiltinScalarFunction::Acosh | BuiltinScalarFunction::Asinh | BuiltinScalarFunction::Atanh @@ -1342,8 +1338,7 @@ impl BuiltinScalarFunction { vec![Exact(vec![Utf8, Utf8]), Exact(vec![LargeUtf8, LargeUtf8])], self.volatility(), ), - BuiltinScalarFunction::Asin - | BuiltinScalarFunction::Atan + BuiltinScalarFunction::Atan | BuiltinScalarFunction::Acosh | BuiltinScalarFunction::Asinh | BuiltinScalarFunction::Atanh @@ -1434,7 +1429,6 @@ impl BuiltinScalarFunction { pub fn aliases(&self) -> &'static [&'static str] { match self { BuiltinScalarFunction::Acosh => &["acosh"], - BuiltinScalarFunction::Asin => &["asin"], BuiltinScalarFunction::Asinh => &["asinh"], BuiltinScalarFunction::Atan => &["atan"], BuiltinScalarFunction::Atanh => &["atanh"], diff --git a/datafusion/expr/src/expr_fn.rs b/datafusion/expr/src/expr_fn.rs index 67bf39050d58..9bd0ce9a4662 100644 --- a/datafusion/expr/src/expr_fn.rs +++ b/datafusion/expr/src/expr_fn.rs @@ -530,7 +530,6 @@ scalar_expr!(Cot, cot, num, "cotangent"); scalar_expr!(Sinh, sinh, num, "hyperbolic sine"); scalar_expr!(Cosh, cosh, num, "hyperbolic cosine"); scalar_expr!(Tanh, tanh, num, "hyperbolic tangent"); -scalar_expr!(Asin, asin, num, "inverse sine"); scalar_expr!(Atan, atan, num, "inverse tangent"); scalar_expr!(Asinh, asinh, num, "inverse hyperbolic sine"); scalar_expr!(Acosh, acosh, num, "inverse hyperbolic cosine"); @@ -1337,7 +1336,6 @@ mod test { test_unary_scalar_expr!(Sinh, sinh); test_unary_scalar_expr!(Cosh, cosh); test_unary_scalar_expr!(Tanh, tanh); - test_unary_scalar_expr!(Asin, asin); test_unary_scalar_expr!(Atan, atan); test_unary_scalar_expr!(Asinh, asinh); test_unary_scalar_expr!(Acosh, acosh); diff --git a/datafusion/functions/src/math/asin.rs b/datafusion/functions/src/math/asin.rs new file mode 100644 index 000000000000..f34bf56840ed --- /dev/null +++ b/datafusion/functions/src/math/asin.rs @@ -0,0 +1,110 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Math function: `asin()`. + +use arrow::array::{ArrayRef, Float32Array, Float64Array}; +use arrow::datatypes::DataType; +use datafusion_common::{exec_err, plan_datafusion_err, DataFusionError, Result}; +use datafusion_expr::ColumnarValue; +use datafusion_expr::{ + utils::generate_signature_error_msg, ScalarUDFImpl, Signature, Volatility, +}; +use std::any::Any; +use std::sync::Arc; + +#[derive(Debug)] +pub struct AsinFunc { + signature: Signature, +} + +impl AsinFunc { + pub fn new() -> Self { + use DataType::*; + Self { + signature: Signature::uniform( + 1, + vec![Float64, Float32], + Volatility::Immutable, + ), + } + } +} + +impl ScalarUDFImpl for AsinFunc { + fn as_any(&self) -> &dyn Any { + self + } + fn name(&self) -> &str { + "asin" + } + + fn signature(&self) -> &Signature { + &self.signature + } + + fn return_type(&self, arg_types: &[DataType]) -> Result { + if arg_types.len() != 1 { + return Err(plan_datafusion_err!( + "{}", + generate_signature_error_msg( + self.name(), + self.signature().clone(), + arg_types, + ) + )); + } + + let arg_type = &arg_types[0]; + + match arg_type { + DataType::Float64 => Ok(DataType::Float64), + DataType::Float32 => Ok(DataType::Float32), + + // For other types (possible values null/int), use Float 64 + _ => Ok(DataType::Float64), + } + } + + fn invoke(&self, args: &[ColumnarValue]) -> Result { + let args = ColumnarValue::values_to_arrays(args)?; + + let arr: ArrayRef = match args[0].data_type() { + DataType::Float64 => Arc::new(make_function_scalar_inputs_return_type!( + &args[0], + self.name(), + Float64Array, + Float64Array, + { f64::asin } + )), + DataType::Float32 => Arc::new(make_function_scalar_inputs_return_type!( + &args[0], + self.name(), + Float32Array, + Float32Array, + { f32::asin } + )), + other => { + return exec_err!( + "Unsupported data type {other:?} for function {}", + self.name() + ) + } + }; + Ok(ColumnarValue::Array(arr)) + } +} diff --git a/datafusion/functions/src/math/mod.rs b/datafusion/functions/src/math/mod.rs index 65752a0fe4d9..3741cc2802bb 100644 --- a/datafusion/functions/src/math/mod.rs +++ b/datafusion/functions/src/math/mod.rs @@ -19,12 +19,14 @@ mod abs; mod acos; +mod asin; mod nans; // create UDFs make_udf_function!(nans::IsNanFunc, ISNAN, isnan); make_udf_function!(abs::AbsFunc, ABS, abs); make_udf_function!(acos::AcosFunc, ACOS, acos); +make_udf_function!(asin::AsinFunc, ASIN, asin); // Export the functions out of this package, both as expr_fn as well as a list of functions export_functions!( @@ -38,5 +40,10 @@ export_functions!( acos, num, "returns the arc cosine or inverse cosine of a number" + ), + ( + asin, + num, + "returns the arc sine or inverse sine of a number" ) ); diff --git a/datafusion/physical-expr/src/functions.rs b/datafusion/physical-expr/src/functions.rs index af079dbd2d12..7b6fad9d5fe2 100644 --- a/datafusion/physical-expr/src/functions.rs +++ b/datafusion/physical-expr/src/functions.rs @@ -261,7 +261,6 @@ pub fn create_physical_fun( ) -> Result { Ok(match fun { // math functions - BuiltinScalarFunction::Asin => Arc::new(math_expressions::asin), BuiltinScalarFunction::Atan => Arc::new(math_expressions::atan), BuiltinScalarFunction::Acosh => Arc::new(math_expressions::acosh), BuiltinScalarFunction::Asinh => Arc::new(math_expressions::asinh), diff --git a/datafusion/proto/proto/datafusion.proto b/datafusion/proto/proto/datafusion.proto index 2d729ffc5b3e..2f2b9c2526bf 100644 --- a/datafusion/proto/proto/datafusion.proto +++ b/datafusion/proto/proto/datafusion.proto @@ -549,7 +549,7 @@ enum ScalarFunction { // The first enum value must be zero for open enums unknown = 0; // 1 was Acos - Asin = 2; + // 2 was Asin Atan = 3; Ascii = 4; Ceil = 5; diff --git a/datafusion/proto/src/generated/pbjson.rs b/datafusion/proto/src/generated/pbjson.rs index 5f05b8546f68..ea26b87c534c 100644 --- a/datafusion/proto/src/generated/pbjson.rs +++ b/datafusion/proto/src/generated/pbjson.rs @@ -22322,7 +22322,6 @@ impl serde::Serialize for ScalarFunction { { let variant = match self { Self::Unknown => "unknown", - Self::Asin => "Asin", Self::Atan => "Atan", Self::Ascii => "Ascii", Self::Ceil => "Ceil", @@ -22464,7 +22463,6 @@ impl<'de> serde::Deserialize<'de> for ScalarFunction { { const FIELDS: &[&str] = &[ "unknown", - "Asin", "Atan", "Ascii", "Ceil", @@ -22635,7 +22633,6 @@ impl<'de> serde::Deserialize<'de> for ScalarFunction { { match value { "unknown" => Ok(ScalarFunction::Unknown), - "Asin" => Ok(ScalarFunction::Asin), "Atan" => Ok(ScalarFunction::Atan), "Ascii" => Ok(ScalarFunction::Ascii), "Ceil" => Ok(ScalarFunction::Ceil), diff --git a/datafusion/proto/src/generated/prost.rs b/datafusion/proto/src/generated/prost.rs index 252089d5c14d..3a51a3ec4ca9 100644 --- a/datafusion/proto/src/generated/prost.rs +++ b/datafusion/proto/src/generated/prost.rs @@ -2637,7 +2637,7 @@ pub enum ScalarFunction { /// The first enum value must be zero for open enums Unknown = 0, /// 1 was Acos - Asin = 2, + /// 2 was Asin Atan = 3, Ascii = 4, Ceil = 5, @@ -2779,7 +2779,6 @@ impl ScalarFunction { pub fn as_str_name(&self) -> &'static str { match self { ScalarFunction::Unknown => "unknown", - ScalarFunction::Asin => "Asin", ScalarFunction::Atan => "Atan", ScalarFunction::Ascii => "Ascii", ScalarFunction::Ceil => "Ceil", @@ -2915,7 +2914,6 @@ impl ScalarFunction { pub fn from_str_name(value: &str) -> ::core::option::Option { match value { "unknown" => Some(Self::Unknown), - "Asin" => Some(Self::Asin), "Atan" => Some(Self::Atan), "Ascii" => Some(Self::Ascii), "Ceil" => Some(Self::Ceil), diff --git a/datafusion/proto/src/logical_plan/from_proto.rs b/datafusion/proto/src/logical_plan/from_proto.rs index acfa043b88af..d432efad8405 100644 --- a/datafusion/proto/src/logical_plan/from_proto.rs +++ b/datafusion/proto/src/logical_plan/from_proto.rs @@ -52,8 +52,8 @@ use datafusion_expr::{ array_length, array_ndims, array_pop_back, array_pop_front, array_position, array_positions, array_prepend, array_remove, array_remove_all, array_remove_n, array_repeat, array_replace, array_replace_all, array_replace_n, array_resize, - array_slice, array_sort, array_union, arrow_typeof, ascii, asin, asinh, atan, atan2, - atanh, bit_length, btrim, cardinality, cbrt, ceil, character_length, chr, coalesce, + array_slice, array_sort, array_union, arrow_typeof, ascii, asinh, atan, atan2, atanh, + bit_length, btrim, cardinality, cbrt, ceil, character_length, chr, coalesce, concat_expr, concat_ws_expr, cos, cosh, cot, current_date, current_time, date_bin, date_part, date_trunc, degrees, digest, ends_with, exp, expr::{self, InList, Sort, WindowFunction}, @@ -449,7 +449,6 @@ impl From<&protobuf::ScalarFunction> for BuiltinScalarFunction { ScalarFunction::Cos => Self::Cos, ScalarFunction::Tan => Self::Tan, ScalarFunction::Cot => Self::Cot, - ScalarFunction::Asin => Self::Asin, ScalarFunction::Atan => Self::Atan, ScalarFunction::Sinh => Self::Sinh, ScalarFunction::Cosh => Self::Cosh, @@ -1360,7 +1359,6 @@ pub fn parse_expr( match scalar_function { ScalarFunction::Unknown => Err(proto_error("Unknown scalar function")), - ScalarFunction::Asin => Ok(asin(parse_expr(&args[0], registry)?)), ScalarFunction::Asinh => Ok(asinh(parse_expr(&args[0], registry)?)), ScalarFunction::Acosh => Ok(acosh(parse_expr(&args[0], registry)?)), ScalarFunction::Array => Ok(array( diff --git a/datafusion/proto/src/logical_plan/to_proto.rs b/datafusion/proto/src/logical_plan/to_proto.rs index d19830db98ce..fa40bd3e1958 100644 --- a/datafusion/proto/src/logical_plan/to_proto.rs +++ b/datafusion/proto/src/logical_plan/to_proto.rs @@ -1431,7 +1431,6 @@ impl TryFrom<&BuiltinScalarFunction> for protobuf::ScalarFunction { BuiltinScalarFunction::Sinh => Self::Sinh, BuiltinScalarFunction::Cosh => Self::Cosh, BuiltinScalarFunction::Tanh => Self::Tanh, - BuiltinScalarFunction::Asin => Self::Asin, BuiltinScalarFunction::Atan => Self::Atan, BuiltinScalarFunction::Asinh => Self::Asinh, BuiltinScalarFunction::Acosh => Self::Acosh,