mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2025-12-22 22:20:02 +00:00
feat: add isnull function (#3360)
* code fmt * feat: add isnull function * feat: add isnull function
This commit is contained in:
@@ -21,6 +21,7 @@ use once_cell::sync::Lazy;
|
||||
use crate::function::FunctionRef;
|
||||
use crate::scalars::aggregate::{AggregateFunctionMetaRef, AggregateFunctions};
|
||||
use crate::scalars::date::DateFunction;
|
||||
use crate::scalars::expression::ExpressionFunction;
|
||||
use crate::scalars::math::MathFunction;
|
||||
use crate::scalars::numpy::NumpyFunction;
|
||||
use crate::scalars::timestamp::TimestampFunction;
|
||||
@@ -80,6 +81,7 @@ pub static FUNCTION_REGISTRY: Lazy<Arc<FunctionRegistry>> = Lazy::new(|| {
|
||||
NumpyFunction::register(&function_registry);
|
||||
TimestampFunction::register(&function_registry);
|
||||
DateFunction::register(&function_registry);
|
||||
ExpressionFunction::register(&function_registry);
|
||||
|
||||
// Aggregate functions
|
||||
AggregateFunctions::register(&function_registry);
|
||||
|
||||
@@ -14,8 +14,22 @@
|
||||
|
||||
mod binary;
|
||||
mod ctx;
|
||||
mod is_null;
|
||||
mod unary;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use binary::scalar_binary_op;
|
||||
pub use ctx::EvalContext;
|
||||
pub use unary::scalar_unary_op;
|
||||
|
||||
use crate::function_registry::FunctionRegistry;
|
||||
use crate::scalars::expression::is_null::IsNullFunction;
|
||||
|
||||
pub(crate) struct ExpressionFunction;
|
||||
|
||||
impl ExpressionFunction {
|
||||
pub fn register(registry: &FunctionRegistry) {
|
||||
registry.register(Arc::new(IsNullFunction));
|
||||
}
|
||||
}
|
||||
|
||||
109
src/common/function/src/scalars/expression/is_null.rs
Normal file
109
src/common/function/src/scalars/expression/is_null.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
// Copyright 2023 Greptime Team
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::Display;
|
||||
use std::sync::Arc;
|
||||
|
||||
use common_query::error;
|
||||
use common_query::error::{ArrowComputeSnafu, InvalidFuncArgsSnafu};
|
||||
use common_query::prelude::{Signature, Volatility};
|
||||
use datafusion::arrow::array::ArrayRef;
|
||||
use datafusion::arrow::compute::is_null;
|
||||
use datatypes::data_type::ConcreteDataType;
|
||||
use datatypes::prelude::VectorRef;
|
||||
use datatypes::vectors::Helper;
|
||||
use snafu::{ensure, ResultExt};
|
||||
|
||||
use crate::function::{Function, FunctionContext};
|
||||
|
||||
const NAME: &str = "isnull";
|
||||
|
||||
/// The function to check whether an expression is NULL
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct IsNullFunction;
|
||||
|
||||
impl Display for IsNullFunction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", NAME.to_ascii_uppercase())
|
||||
}
|
||||
}
|
||||
|
||||
impl Function for IsNullFunction {
|
||||
fn name(&self) -> &str {
|
||||
NAME
|
||||
}
|
||||
|
||||
fn return_type(&self, _: &[ConcreteDataType]) -> common_query::error::Result<ConcreteDataType> {
|
||||
Ok(ConcreteDataType::boolean_datatype())
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::any(1, Volatility::Immutable)
|
||||
}
|
||||
|
||||
fn eval(
|
||||
&self,
|
||||
_func_ctx: FunctionContext,
|
||||
columns: &[VectorRef],
|
||||
) -> common_query::error::Result<VectorRef> {
|
||||
ensure!(
|
||||
columns.len() == 1,
|
||||
InvalidFuncArgsSnafu {
|
||||
err_msg: format!(
|
||||
"The length of the args is not correct, expect exactly one, have: {}",
|
||||
columns.len()
|
||||
),
|
||||
}
|
||||
);
|
||||
let values = &columns[0];
|
||||
let arrow_array = &values.to_arrow_array();
|
||||
let result = is_null(arrow_array).context(ArrowComputeSnafu)?;
|
||||
|
||||
Helper::try_into_vector(Arc::new(result) as ArrayRef).context(error::FromArrowArraySnafu)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
use common_query::prelude::TypeSignature;
|
||||
use datatypes::scalars::ScalarVector;
|
||||
use datatypes::vectors::{BooleanVector, Float32Vector};
|
||||
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_is_null_function() {
|
||||
let is_null = IsNullFunction;
|
||||
assert_eq!("isnull", is_null.name());
|
||||
assert_eq!(
|
||||
ConcreteDataType::boolean_datatype(),
|
||||
is_null.return_type(&[]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
is_null.signature(),
|
||||
Signature {
|
||||
type_signature: TypeSignature::Any(1),
|
||||
volatility: Volatility::Immutable
|
||||
}
|
||||
);
|
||||
let values = vec![None, Some(3.0), None];
|
||||
|
||||
let args: Vec<VectorRef> = vec![Arc::new(Float32Vector::from(values))];
|
||||
let vector = is_null.eval(FunctionContext::default(), &args).unwrap();
|
||||
let expect: VectorRef = Arc::new(BooleanVector::from_vec(vec![true, false, true]));
|
||||
assert_eq!(expect, vector);
|
||||
}
|
||||
}
|
||||
70
tests/cases/standalone/common/function/expression.result
Normal file
70
tests/cases/standalone/common/function/expression.result
Normal file
@@ -0,0 +1,70 @@
|
||||
CREATE TABLE t(a INTEGER, ts timestamp time index);
|
||||
|
||||
Affected Rows: 0
|
||||
|
||||
INSERT INTO t VALUES (1, 1), (null, 2), (3, 3);
|
||||
|
||||
Affected Rows: 3
|
||||
|
||||
SELECT ISNULL(a) from t;
|
||||
|
||||
+-------------+
|
||||
| isnull(t.a) |
|
||||
+-------------+
|
||||
| false |
|
||||
| true |
|
||||
| false |
|
||||
+-------------+
|
||||
|
||||
SELECT ISNULL(null);
|
||||
|
||||
+--------------+
|
||||
| isnull(NULL) |
|
||||
+--------------+
|
||||
| true |
|
||||
+--------------+
|
||||
|
||||
SELECT ISNULL(1);
|
||||
|
||||
+------------------+
|
||||
| isnull(Int64(1)) |
|
||||
+------------------+
|
||||
| false |
|
||||
+------------------+
|
||||
|
||||
SELECT ISNULL(-1);
|
||||
|
||||
+-------------------+
|
||||
| isnull(Int64(-1)) |
|
||||
+-------------------+
|
||||
| false |
|
||||
+-------------------+
|
||||
|
||||
SELECT ISNULL(1.0);
|
||||
|
||||
+--------------------+
|
||||
| isnull(Float64(1)) |
|
||||
+--------------------+
|
||||
| false |
|
||||
+--------------------+
|
||||
|
||||
SELECT ISNULL(true);
|
||||
|
||||
+-----------------------+
|
||||
| isnull(Boolean(true)) |
|
||||
+-----------------------+
|
||||
| false |
|
||||
+-----------------------+
|
||||
|
||||
SELECT ISNULL('string');
|
||||
|
||||
+------------------------+
|
||||
| isnull(Utf8("string")) |
|
||||
+------------------------+
|
||||
| false |
|
||||
+------------------------+
|
||||
|
||||
DROP TABLE t;
|
||||
|
||||
Affected Rows: 0
|
||||
|
||||
19
tests/cases/standalone/common/function/expression.sql
Normal file
19
tests/cases/standalone/common/function/expression.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
CREATE TABLE t(a INTEGER, ts timestamp time index);
|
||||
|
||||
INSERT INTO t VALUES (1, 1), (null, 2), (3, 3);
|
||||
|
||||
SELECT ISNULL(a) from t;
|
||||
|
||||
SELECT ISNULL(null);
|
||||
|
||||
SELECT ISNULL(1);
|
||||
|
||||
SELECT ISNULL(-1);
|
||||
|
||||
SELECT ISNULL(1.0);
|
||||
|
||||
SELECT ISNULL(true);
|
||||
|
||||
SELECT ISNULL('string');
|
||||
|
||||
DROP TABLE t;
|
||||
Reference in New Issue
Block a user