datafusion_functions/core/
nvl.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
18use crate::core::coalesce::CoalesceFunc;
19use arrow::datatypes::{DataType, FieldRef};
20use datafusion_common::Result;
21use datafusion_expr::simplify::{ExprSimplifyResult, SimplifyInfo};
22use datafusion_expr::{
23    ColumnarValue, Documentation, Expr, ReturnFieldArgs, ScalarFunctionArgs,
24    ScalarUDFImpl, Signature, Volatility,
25};
26use datafusion_macros::user_doc;
27
28#[user_doc(
29    doc_section(label = "Conditional Functions"),
30    description = "Returns _expression2_ if _expression1_ is NULL otherwise it returns _expression1_ and _expression2_ is not evaluated. This function can be used to substitute a default value for NULL values.",
31    syntax_example = "nvl(expression1, expression2)",
32    sql_example = r#"```sql
33> select nvl(null, 'a');
34+---------------------+
35| nvl(NULL,Utf8("a")) |
36+---------------------+
37| a                   |
38+---------------------+\
39> select nvl('b', 'a');
40+--------------------------+
41| nvl(Utf8("b"),Utf8("a")) |
42+--------------------------+
43| b                        |
44+--------------------------+
45```
46"#,
47    argument(
48        name = "expression1",
49        description = "Expression to return if not null. Can be a constant, column, or function, and any combination of operators."
50    ),
51    argument(
52        name = "expression2",
53        description = "Expression to return if expr1 is null. Can be a constant, column, or function, and any combination of operators."
54    )
55)]
56#[derive(Debug, PartialEq, Eq, Hash)]
57pub struct NVLFunc {
58    coalesce: CoalesceFunc,
59    aliases: Vec<String>,
60}
61
62/// Currently supported types by the nvl/ifnull function.
63/// The order of these types correspond to the order on which coercion applies
64/// This should thus be from least informative to most informative
65static SUPPORTED_NVL_TYPES: &[DataType] = &[
66    DataType::Boolean,
67    DataType::UInt8,
68    DataType::UInt16,
69    DataType::UInt32,
70    DataType::UInt64,
71    DataType::Int8,
72    DataType::Int16,
73    DataType::Int32,
74    DataType::Int64,
75    DataType::Float32,
76    DataType::Float64,
77    DataType::Utf8View,
78    DataType::Utf8,
79    DataType::LargeUtf8,
80];
81
82impl Default for NVLFunc {
83    fn default() -> Self {
84        Self::new()
85    }
86}
87
88impl NVLFunc {
89    pub fn new() -> Self {
90        Self {
91            coalesce: CoalesceFunc {
92                signature: Signature::uniform(
93                    2,
94                    SUPPORTED_NVL_TYPES.to_vec(),
95                    Volatility::Immutable,
96                ),
97            },
98            aliases: vec![String::from("ifnull")],
99        }
100    }
101}
102
103impl ScalarUDFImpl for NVLFunc {
104    fn as_any(&self) -> &dyn std::any::Any {
105        self
106    }
107
108    fn name(&self) -> &str {
109        "nvl"
110    }
111
112    fn signature(&self) -> &Signature {
113        &self.coalesce.signature
114    }
115
116    fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
117        self.coalesce.return_type(arg_types)
118    }
119
120    fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
121        self.coalesce.return_field_from_args(args)
122    }
123
124    fn simplify(
125        &self,
126        args: Vec<Expr>,
127        info: &dyn SimplifyInfo,
128    ) -> Result<ExprSimplifyResult> {
129        self.coalesce.simplify(args, info)
130    }
131
132    fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
133        self.coalesce.invoke_with_args(args)
134    }
135
136    fn conditional_arguments<'a>(
137        &self,
138        args: &'a [Expr],
139    ) -> Option<(Vec<&'a Expr>, Vec<&'a Expr>)> {
140        self.coalesce.conditional_arguments(args)
141    }
142
143    fn short_circuits(&self) -> bool {
144        self.coalesce.short_circuits()
145    }
146
147    fn aliases(&self) -> &[String] {
148        &self.aliases
149    }
150
151    fn documentation(&self) -> Option<&Documentation> {
152        self.doc()
153    }
154}