common_function/scalars/expression/
is_null.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt;
16use std::fmt::Display;
17use std::sync::Arc;
18
19use common_query::error;
20use common_query::error::{ArrowComputeSnafu, InvalidFuncArgsSnafu};
21use common_query::prelude::{Signature, Volatility};
22use datafusion::arrow::array::ArrayRef;
23use datafusion::arrow::compute::is_null;
24use datatypes::data_type::ConcreteDataType;
25use datatypes::prelude::VectorRef;
26use datatypes::vectors::Helper;
27use snafu::{ensure, ResultExt};
28
29use crate::function::{Function, FunctionContext};
30
31const NAME: &str = "isnull";
32
33/// The function to check whether an expression is NULL
34#[derive(Clone, Debug, Default)]
35pub struct IsNullFunction;
36
37impl Display for IsNullFunction {
38    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39        write!(f, "{}", NAME.to_ascii_uppercase())
40    }
41}
42
43impl Function for IsNullFunction {
44    fn name(&self) -> &str {
45        NAME
46    }
47
48    fn return_type(&self, _: &[ConcreteDataType]) -> common_query::error::Result<ConcreteDataType> {
49        Ok(ConcreteDataType::boolean_datatype())
50    }
51
52    fn signature(&self) -> Signature {
53        Signature::any(1, Volatility::Immutable)
54    }
55
56    fn eval(
57        &self,
58        _func_ctx: &FunctionContext,
59        columns: &[VectorRef],
60    ) -> common_query::error::Result<VectorRef> {
61        ensure!(
62            columns.len() == 1,
63            InvalidFuncArgsSnafu {
64                err_msg: format!(
65                    "The length of the args is not correct, expect exactly one, have: {}",
66                    columns.len()
67                ),
68            }
69        );
70        let values = &columns[0];
71        let arrow_array = &values.to_arrow_array();
72        let result = is_null(arrow_array).context(ArrowComputeSnafu)?;
73
74        Helper::try_into_vector(Arc::new(result) as ArrayRef).context(error::FromArrowArraySnafu)
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use std::sync::Arc;
81
82    use common_query::prelude::TypeSignature;
83    use datatypes::scalars::ScalarVector;
84    use datatypes::vectors::{BooleanVector, Float32Vector};
85
86    use super::*;
87    #[test]
88    fn test_is_null_function() {
89        let is_null = IsNullFunction;
90        assert_eq!("isnull", is_null.name());
91        assert_eq!(
92            ConcreteDataType::boolean_datatype(),
93            is_null.return_type(&[]).unwrap()
94        );
95        assert_eq!(
96            is_null.signature(),
97            Signature {
98                type_signature: TypeSignature::Any(1),
99                volatility: Volatility::Immutable
100            }
101        );
102        let values = vec![None, Some(3.0), None];
103
104        let args: Vec<VectorRef> = vec![Arc::new(Float32Vector::from(values))];
105        let vector = is_null.eval(&FunctionContext::default(), &args).unwrap();
106        let expect: VectorRef = Arc::new(BooleanVector::from_vec(vec![true, false, true]));
107        assert_eq!(expect, vector);
108    }
109}