datafusion_functions/math/
nans.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Math function: `isnan()`.
19
20use arrow::datatypes::{DataType, Float32Type, Float64Type};
21use datafusion_common::{exec_err, Result};
22use datafusion_expr::{ColumnarValue, ScalarFunctionArgs, TypeSignature};
23
24use arrow::array::{ArrayRef, AsArray, BooleanArray};
25use datafusion_expr::{Documentation, ScalarUDFImpl, Signature, Volatility};
26use datafusion_macros::user_doc;
27use std::any::Any;
28use std::sync::Arc;
29
30#[user_doc(
31    doc_section(label = "Math Functions"),
32    description = "Returns true if a given number is +NaN or -NaN otherwise returns false.",
33    syntax_example = "isnan(numeric_expression)",
34    standard_argument(name = "numeric_expression", prefix = "Numeric")
35)]
36#[derive(Debug)]
37pub struct IsNanFunc {
38    signature: Signature,
39}
40
41impl Default for IsNanFunc {
42    fn default() -> Self {
43        Self::new()
44    }
45}
46
47impl IsNanFunc {
48    pub fn new() -> Self {
49        use DataType::*;
50        Self {
51            signature: Signature::one_of(
52                vec![
53                    TypeSignature::Exact(vec![Float32]),
54                    TypeSignature::Exact(vec![Float64]),
55                ],
56                Volatility::Immutable,
57            ),
58        }
59    }
60}
61
62impl ScalarUDFImpl for IsNanFunc {
63    fn as_any(&self) -> &dyn Any {
64        self
65    }
66    fn name(&self) -> &str {
67        "isnan"
68    }
69
70    fn signature(&self) -> &Signature {
71        &self.signature
72    }
73
74    fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
75        Ok(DataType::Boolean)
76    }
77
78    fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
79        let args = ColumnarValue::values_to_arrays(&args.args)?;
80
81        let arr: ArrayRef = match args[0].data_type() {
82            DataType::Float64 => Arc::new(BooleanArray::from_unary(
83                args[0].as_primitive::<Float64Type>(),
84                f64::is_nan,
85            )) as ArrayRef,
86
87            DataType::Float32 => Arc::new(BooleanArray::from_unary(
88                args[0].as_primitive::<Float32Type>(),
89                f32::is_nan,
90            )) as ArrayRef,
91            other => {
92                return exec_err!(
93                    "Unsupported data type {other:?} for function {}",
94                    self.name()
95                )
96            }
97        };
98        Ok(ColumnarValue::Array(arr))
99    }
100
101    fn documentation(&self) -> Option<&Documentation> {
102        self.doc()
103    }
104}