datafusion_extra_functions/
mode.rs1use datafusion::{arrow, common as df_common, error, logical_expr};
19use std::{any, fmt};
20
21use crate::common;
22
23make_udaf_expr_and_func!(
24 ModeFunction,
25 mode,
26 x,
27 "Calculates the most frequent value.",
28 mode_udaf
29);
30
31#[derive(Eq, Hash, PartialEq)]
36pub struct ModeFunction {
37 signature: logical_expr::Signature,
38}
39
40impl fmt::Debug for ModeFunction {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 f.debug_struct("ModeFunction")
43 .field("signature", &self.signature)
44 .finish()
45 }
46}
47
48impl Default for ModeFunction {
49 fn default() -> Self {
50 Self::new()
51 }
52}
53
54impl ModeFunction {
55 pub fn new() -> Self {
56 Self {
57 signature: logical_expr::Signature::variadic_any(logical_expr::Volatility::Immutable),
58 }
59 }
60}
61
62impl logical_expr::AggregateUDFImpl for ModeFunction {
63 fn as_any(&self) -> &dyn any::Any {
64 self
65 }
66
67 fn name(&self) -> &str {
68 "mode"
69 }
70
71 fn signature(&self) -> &logical_expr::Signature {
72 &self.signature
73 }
74
75 fn return_type(
76 &self,
77 arg_types: &[arrow::datatypes::DataType],
78 ) -> error::Result<arrow::datatypes::DataType> {
79 Ok(arg_types[0].clone())
80 }
81
82 fn state_fields(
83 &self,
84 args: logical_expr::function::StateFieldsArgs,
85 ) -> error::Result<Vec<arrow::datatypes::FieldRef>> {
86 let value_type = args.input_fields[0].data_type().clone();
87
88 Ok(vec![
89 arrow::datatypes::Field::new("values", value_type, true).into(),
90 arrow::datatypes::Field::new("frequencies", arrow::datatypes::DataType::UInt64, true)
91 .into(),
92 ])
93 }
94
95 fn accumulator(
96 &self,
97 acc_args: logical_expr::function::AccumulatorArgs,
98 ) -> error::Result<Box<dyn logical_expr::Accumulator>> {
99 let data_type = &acc_args.exprs[0].data_type(acc_args.schema)?;
100
101 let accumulator: Box<dyn logical_expr::Accumulator> = match data_type {
102 arrow::datatypes::DataType::Int8 => Box::new(common::mode::PrimitiveModeAccumulator::<
103 arrow::datatypes::Int8Type,
104 >::new(data_type)),
105 arrow::datatypes::DataType::Int16 => {
106 Box::new(common::mode::PrimitiveModeAccumulator::<
107 arrow::datatypes::Int16Type,
108 >::new(data_type))
109 }
110 arrow::datatypes::DataType::Int32 => {
111 Box::new(common::mode::PrimitiveModeAccumulator::<
112 arrow::datatypes::Int32Type,
113 >::new(data_type))
114 }
115 arrow::datatypes::DataType::Int64 => {
116 Box::new(common::mode::PrimitiveModeAccumulator::<
117 arrow::datatypes::Int64Type,
118 >::new(data_type))
119 }
120 arrow::datatypes::DataType::UInt8 => {
121 Box::new(common::mode::PrimitiveModeAccumulator::<
122 arrow::datatypes::UInt8Type,
123 >::new(data_type))
124 }
125 arrow::datatypes::DataType::UInt16 => {
126 Box::new(common::mode::PrimitiveModeAccumulator::<
127 arrow::datatypes::UInt16Type,
128 >::new(data_type))
129 }
130 arrow::datatypes::DataType::UInt32 => {
131 Box::new(common::mode::PrimitiveModeAccumulator::<
132 arrow::datatypes::UInt32Type,
133 >::new(data_type))
134 }
135 arrow::datatypes::DataType::UInt64 => {
136 Box::new(common::mode::PrimitiveModeAccumulator::<
137 arrow::datatypes::UInt64Type,
138 >::new(data_type))
139 }
140
141 arrow::datatypes::DataType::Date32 => {
142 Box::new(common::mode::PrimitiveModeAccumulator::<
143 arrow::datatypes::Date32Type,
144 >::new(data_type))
145 }
146 arrow::datatypes::DataType::Date64 => {
147 Box::new(common::mode::PrimitiveModeAccumulator::<
148 arrow::datatypes::Date64Type,
149 >::new(data_type))
150 }
151 arrow::datatypes::DataType::Time32(arrow::datatypes::TimeUnit::Millisecond) => {
152 Box::new(common::mode::PrimitiveModeAccumulator::<
153 arrow::datatypes::Time32MillisecondType,
154 >::new(data_type))
155 }
156 arrow::datatypes::DataType::Time32(arrow::datatypes::TimeUnit::Second) => {
157 Box::new(common::mode::PrimitiveModeAccumulator::<
158 arrow::datatypes::Time32SecondType,
159 >::new(data_type))
160 }
161 arrow::datatypes::DataType::Time64(arrow::datatypes::TimeUnit::Microsecond) => {
162 Box::new(common::mode::PrimitiveModeAccumulator::<
163 arrow::datatypes::Time64MicrosecondType,
164 >::new(data_type))
165 }
166 arrow::datatypes::DataType::Time64(arrow::datatypes::TimeUnit::Nanosecond) => {
167 Box::new(common::mode::PrimitiveModeAccumulator::<
168 arrow::datatypes::Time64NanosecondType,
169 >::new(data_type))
170 }
171 arrow::datatypes::DataType::Timestamp(arrow::datatypes::TimeUnit::Microsecond, _) => {
172 Box::new(common::mode::PrimitiveModeAccumulator::<
173 arrow::datatypes::TimestampMicrosecondType,
174 >::new(data_type))
175 }
176 arrow::datatypes::DataType::Timestamp(arrow::datatypes::TimeUnit::Millisecond, _) => {
177 Box::new(common::mode::PrimitiveModeAccumulator::<
178 arrow::datatypes::TimestampMillisecondType,
179 >::new(data_type))
180 }
181 arrow::datatypes::DataType::Timestamp(arrow::datatypes::TimeUnit::Nanosecond, _) => {
182 Box::new(common::mode::PrimitiveModeAccumulator::<
183 arrow::datatypes::TimestampNanosecondType,
184 >::new(data_type))
185 }
186 arrow::datatypes::DataType::Timestamp(arrow::datatypes::TimeUnit::Second, _) => {
187 Box::new(common::mode::PrimitiveModeAccumulator::<
188 arrow::datatypes::TimestampSecondType,
189 >::new(data_type))
190 }
191
192 arrow::datatypes::DataType::Float16 => Box::new(common::mode::FloatModeAccumulator::<
193 arrow::datatypes::Float16Type,
194 >::new(data_type)),
195 arrow::datatypes::DataType::Float32 => Box::new(common::mode::FloatModeAccumulator::<
196 arrow::datatypes::Float32Type,
197 >::new(data_type)),
198 arrow::datatypes::DataType::Float64 => Box::new(common::mode::FloatModeAccumulator::<
199 arrow::datatypes::Float64Type,
200 >::new(data_type)),
201
202 arrow::datatypes::DataType::Utf8
203 | arrow::datatypes::DataType::Utf8View
204 | arrow::datatypes::DataType::LargeUtf8 => {
205 Box::new(common::mode::BytesModeAccumulator::new(data_type))
206 }
207 _ => {
208 return df_common::not_impl_err!(
209 "Unsupported data type: {:?} for mode function",
210 data_type
211 );
212 }
213 };
214
215 Ok(accumulator)
216 }
217}