Skip to main content

datafusion_functions_aggregate/
any_value.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
18//! Defines the ANY_VALUE aggregation.
19
20use std::fmt::Debug;
21use std::hash::Hash;
22use std::sync::Arc;
23
24use arrow::datatypes::{DataType, Field, FieldRef};
25use datafusion_common::{Result, not_impl_err};
26use datafusion_expr::function::{AccumulatorArgs, StateFieldsArgs};
27use datafusion_expr::utils::{AggregateOrderSensitivity, format_state_name};
28use datafusion_expr::{
29    Accumulator, AggregateUDFImpl, Documentation, Signature, Volatility,
30};
31use datafusion_macros::user_doc;
32
33use crate::first_last::TrivialFirstValueAccumulator;
34
35make_udaf_expr_and_func!(
36    AnyValue,
37    any_value,
38    expression,
39    "Returns an arbitrary non-null value",
40    any_value_udaf
41);
42
43#[user_doc(
44    doc_section(label = "General Functions"),
45    description = "Returns an arbitrary non-null value from a group, or NULL if the group contains only NULL values.",
46    syntax_example = "any_value(expression)",
47    sql_example = r#"```sql
48> SELECT any_value(column_name) FROM table_name;
49+------------------------+
50| any_value(column_name) |
51+------------------------+
52| arbitrary_value        |
53+------------------------+
54```"#,
55    standard_argument(name = "expression",)
56)]
57#[derive(PartialEq, Eq, Hash, Debug)]
58pub struct AnyValue {
59    signature: Signature,
60}
61
62impl Default for AnyValue {
63    fn default() -> Self {
64        Self::new()
65    }
66}
67
68impl AnyValue {
69    pub fn new() -> Self {
70        Self {
71            signature: Signature::any(1, Volatility::Immutable),
72        }
73    }
74}
75
76impl AggregateUDFImpl for AnyValue {
77    fn name(&self) -> &str {
78        "any_value"
79    }
80
81    fn signature(&self) -> &Signature {
82        &self.signature
83    }
84
85    fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
86        not_impl_err!("Not called because return_field is implemented")
87    }
88
89    fn return_field(&self, arg_fields: &[FieldRef]) -> Result<FieldRef> {
90        Ok(Arc::new(
91            Field::new(self.name(), arg_fields[0].data_type().clone(), true)
92                .with_metadata(arg_fields[0].metadata().clone()),
93        ))
94    }
95
96    fn accumulator(&self, acc_args: AccumulatorArgs) -> Result<Box<dyn Accumulator>> {
97        TrivialFirstValueAccumulator::try_new(acc_args.return_field.data_type(), true)
98            .map(|acc| Box::new(acc) as _)
99    }
100
101    fn state_fields(&self, args: StateFieldsArgs) -> Result<Vec<FieldRef>> {
102        Ok(vec![
103            Field::new(
104                format_state_name(args.name, "any_value"),
105                args.return_type().clone(),
106                true,
107            )
108            .into(),
109            Field::new(
110                format_state_name(args.name, "any_value_is_set"),
111                DataType::Boolean,
112                true,
113            )
114            .into(),
115        ])
116    }
117
118    fn order_sensitivity(&self) -> AggregateOrderSensitivity {
119        AggregateOrderSensitivity::Insensitive
120    }
121
122    fn documentation(&self) -> Option<&Documentation> {
123        self.doc()
124    }
125}