datafusion_functions/core/
coalesce.rs1use arrow::datatypes::{DataType, Field, FieldRef};
19use datafusion_common::{Result, exec_err, internal_err, plan_err};
20use datafusion_expr::binary::try_type_union_resolution;
21use datafusion_expr::conditional_expressions::CaseBuilder;
22use datafusion_expr::simplify::{ExprSimplifyResult, SimplifyContext};
23use datafusion_expr::{
24 ColumnarValue, Documentation, Expr, ReturnFieldArgs, ScalarFunctionArgs,
25};
26use datafusion_expr::{ScalarUDFImpl, Signature, Volatility};
27use datafusion_macros::user_doc;
28use itertools::Itertools;
29
30#[user_doc(
31 doc_section(label = "Conditional Functions"),
32 description = "Returns the first of its arguments that is not _null_. Returns _null_ if all arguments are _null_. This function is often used to substitute a default value for _null_ values.",
33 syntax_example = "coalesce(expression1[, ..., expression_n])",
34 sql_example = r#"```sql
35> select coalesce(null, null, 'datafusion');
36+----------------------------------------+
37| coalesce(NULL,NULL,Utf8("datafusion")) |
38+----------------------------------------+
39| datafusion |
40+----------------------------------------+
41```"#,
42 argument(
43 name = "expression1, expression_n",
44 description = "Expression to use if previous expressions are _null_. Can be a constant, column, or function, and any combination of arithmetic operators. Pass as many expression arguments as necessary."
45 )
46)]
47#[derive(Debug, PartialEq, Eq, Hash)]
48pub struct CoalesceFunc {
49 pub(super) signature: Signature,
50}
51
52impl Default for CoalesceFunc {
53 fn default() -> Self {
54 CoalesceFunc::new()
55 }
56}
57
58impl CoalesceFunc {
59 pub fn new() -> Self {
60 Self {
61 signature: Signature::user_defined(Volatility::Immutable),
62 }
63 }
64}
65
66impl ScalarUDFImpl for CoalesceFunc {
67 fn name(&self) -> &str {
68 "coalesce"
69 }
70
71 fn signature(&self) -> &Signature {
72 &self.signature
73 }
74
75 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
76 internal_err!("return_field_from_args should be called instead")
77 }
78
79 fn return_field_from_args(&self, args: ReturnFieldArgs) -> Result<FieldRef> {
80 let nullable = args.arg_fields.iter().all(|f| f.is_nullable());
82 let return_type = args
83 .arg_fields
84 .iter()
85 .map(|f| f.data_type())
86 .find_or_first(|d| !d.is_null())
87 .unwrap()
88 .clone();
89 Ok(Field::new(self.name(), return_type, nullable).into())
90 }
91
92 fn simplify(
93 &self,
94 args: Vec<Expr>,
95 _info: &SimplifyContext,
96 ) -> Result<ExprSimplifyResult> {
97 if args.is_empty() {
98 return plan_err!("coalesce must have at least one argument");
99 }
100 if args.len() == 1 {
101 return Ok(ExprSimplifyResult::Simplified(
102 args.into_iter().next().unwrap(),
103 ));
104 }
105
106 let n = args.len();
107 let (init, last_elem) = args.split_at(n - 1);
108 let whens = init
109 .iter()
110 .map(|x| x.clone().is_not_null())
111 .collect::<Vec<_>>();
112 let cases = init.to_vec();
113 Ok(ExprSimplifyResult::Simplified(
114 CaseBuilder::new(None, whens, cases, Some(Box::new(last_elem[0].clone())))
115 .end()?,
116 ))
117 }
118
119 fn invoke_with_args(&self, _args: ScalarFunctionArgs) -> Result<ColumnarValue> {
121 internal_err!("coalesce should have been simplified to case")
122 }
123
124 fn conditional_arguments<'a>(
125 &self,
126 args: &'a [Expr],
127 ) -> Option<(Vec<&'a Expr>, Vec<&'a Expr>)> {
128 let eager = vec![&args[0]];
129 let lazy = args[1..].iter().collect();
130 Some((eager, lazy))
131 }
132
133 fn short_circuits(&self) -> bool {
134 true
135 }
136
137 fn coerce_types(&self, arg_types: &[DataType]) -> Result<Vec<DataType>> {
138 if arg_types.is_empty() {
139 return exec_err!("coalesce must have at least one argument");
140 }
141
142 try_type_union_resolution(arg_types)
143 }
144
145 fn documentation(&self) -> Option<&Documentation> {
146 self.doc()
147 }
148}