datafusion_functions/core/
nvl.rs1use 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
62static 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}