common_function/
helper.rs1use api::v1::meta::ResolveStrategy;
16use common_query::error::{
17 InvalidFuncArgsSnafu, InvalidInputTypeSnafu, Result, UnsupportedInputDataTypeSnafu,
18};
19use datafusion_expr::{Signature, TypeSignature, Volatility};
20use datatypes::arrow::datatypes::DataType;
21use datatypes::prelude::ConcreteDataType;
22use datatypes::types::cast::cast;
23use datatypes::value::ValueRef;
24use snafu::{OptionExt, ResultExt};
25
26pub(crate) const INTEGER_TYPES: &[DataType] = &[
28 DataType::Int8,
29 DataType::Int16,
30 DataType::Int32,
31 DataType::Int64,
32 DataType::UInt8,
33 DataType::UInt16,
34 DataType::UInt32,
35 DataType::UInt64,
36];
37
38pub(crate) const NUMERICS: &[DataType] = &[
40 DataType::Int8,
41 DataType::Int16,
42 DataType::Int32,
43 DataType::Int64,
44 DataType::UInt8,
45 DataType::UInt16,
46 DataType::UInt32,
47 DataType::UInt64,
48 DataType::Float16,
49 DataType::Float32,
50 DataType::Float64,
51];
52
53pub(crate) fn one_of_sigs2(args1: Vec<DataType>, args2: Vec<DataType>) -> Signature {
55 let mut sigs = Vec::with_capacity(args1.len() * args2.len());
56
57 for arg1 in &args1 {
58 for arg2 in &args2 {
59 sigs.push(TypeSignature::Exact(vec![arg1.clone(), arg2.clone()]));
60 }
61 }
62
63 Signature::one_of(sigs, Volatility::Immutable)
64}
65
66pub fn cast_u64(value: &ValueRef) -> Result<Option<u64>> {
68 cast(value.clone().into(), &ConcreteDataType::uint64_datatype())
69 .context(InvalidInputTypeSnafu {
70 err_msg: format!(
71 "Failed to cast input into uint64, actual type: {:#?}",
72 value.data_type(),
73 ),
74 })
75 .map(|v| v.as_u64())
76}
77
78pub fn cast_u32(value: &ValueRef) -> Result<Option<u32>> {
80 cast(value.clone().into(), &ConcreteDataType::uint32_datatype())
81 .context(InvalidInputTypeSnafu {
82 err_msg: format!(
83 "Failed to cast input into uint32, actual type: {:#?}",
84 value.data_type(),
85 ),
86 })
87 .map(|v| v.as_u64().map(|v| v as u32))
88}
89
90pub fn parse_resolve_strategy(strategy: &str) -> Result<ResolveStrategy> {
92 ResolveStrategy::from_str_name(strategy).context(InvalidFuncArgsSnafu {
93 err_msg: format!("Invalid resolve strategy: {}", strategy),
94 })
95}
96
97pub fn default_parallelism() -> u32 {
99 64
100}
101
102pub fn default_resolve_strategy() -> ResolveStrategy {
104 ResolveStrategy::UseLatest
105}
106
107pub fn get_string_from_params<'a>(
112 params: &'a [ValueRef<'a>],
113 index: usize,
114 fn_name: &'a str,
115) -> Result<&'a str> {
116 let ValueRef::String(s) = ¶ms[index] else {
117 return UnsupportedInputDataTypeSnafu {
118 function: fn_name,
119 datatypes: params.iter().map(|v| v.data_type()).collect::<Vec<_>>(),
120 }
121 .fail();
122 };
123 Ok(s)
124}
125
126macro_rules! with_match_timestamp_types {
127 ($data_type:expr, | $_t:tt $T:ident | $body:tt) => {{
128 macro_rules! __with_ty__ {
129 ( $_t $T:ident ) => {
130 $body
131 };
132 }
133
134 use datafusion_common::DataFusionError;
135 use datafusion_common::arrow::datatypes::{
136 TimeUnit, TimestampMicrosecondType, TimestampMillisecondType, TimestampNanosecondType,
137 TimestampSecondType,
138 };
139
140 match $data_type {
141 DataType::Timestamp(TimeUnit::Second, _) => Ok(__with_ty__! { TimestampSecondType }),
142 DataType::Timestamp(TimeUnit::Millisecond, _) => {
143 Ok(__with_ty__! { TimestampMillisecondType })
144 }
145 DataType::Timestamp(TimeUnit::Microsecond, _) => {
146 Ok(__with_ty__! { TimestampMicrosecondType })
147 }
148 DataType::Timestamp(TimeUnit::Nanosecond, _) => {
149 Ok(__with_ty__! { TimestampNanosecondType })
150 }
151 _ => Err(DataFusionError::Execution(format!(
152 "not expected data type: '{}'",
153 $data_type
154 ))),
155 }
156 }};
157}
158
159pub(crate) use with_match_timestamp_types;
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164
165 #[test]
166 fn test_parse_resolve_strategy() {
167 assert_eq!(
168 parse_resolve_strategy("UseLatest").unwrap(),
169 ResolveStrategy::UseLatest
170 );
171 }
172}