use crate::string::common::to_upper;
use crate::utils::utf8_to_str_type;
use arrow::datatypes::DataType;
use datafusion_common::Result;
use datafusion_expr::ColumnarValue;
use datafusion_expr::{ScalarUDFImpl, Signature, Volatility};
use std::any::Any;
#[derive(Debug)]
pub struct UpperFunc {
signature: Signature,
}
impl Default for UpperFunc {
fn default() -> Self {
Self::new()
}
}
impl UpperFunc {
pub fn new() -> Self {
use DataType::*;
Self {
signature: Signature::uniform(
1,
vec![Utf8, LargeUtf8],
Volatility::Immutable,
),
}
}
}
impl ScalarUDFImpl for UpperFunc {
fn as_any(&self) -> &dyn Any {
self
}
fn name(&self) -> &str {
"upper"
}
fn signature(&self) -> &Signature {
&self.signature
}
fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
utf8_to_str_type(&arg_types[0], "upper")
}
fn invoke(&self, args: &[ColumnarValue]) -> Result<ColumnarValue> {
to_upper(args, "upper")
}
}
#[cfg(test)]
mod tests {
use super::*;
use arrow::array::{ArrayRef, StringArray};
use std::sync::Arc;
fn to_upper(input: ArrayRef, expected: ArrayRef) -> Result<()> {
let func = UpperFunc::new();
let args = vec![ColumnarValue::Array(input)];
let result = match func.invoke(&args)? {
ColumnarValue::Array(result) => result,
_ => unreachable!(),
};
assert_eq!(&expected, &result);
Ok(())
}
#[test]
fn upper_maybe_optimization() -> Result<()> {
let input = Arc::new(StringArray::from(vec![
Some("农历新年"),
None,
Some("datafusion"),
Some("0123456789"),
Some(""),
])) as ArrayRef;
let expected = Arc::new(StringArray::from(vec![
Some("农历新年"),
None,
Some("DATAFUSION"),
Some("0123456789"),
Some(""),
])) as ArrayRef;
to_upper(input, expected)
}
#[test]
fn upper_full_optimization() -> Result<()> {
let input = Arc::new(StringArray::from(vec![
Some("arrow"),
None,
Some("datafusion"),
Some("0123456789"),
Some(""),
])) as ArrayRef;
let expected = Arc::new(StringArray::from(vec![
Some("ARROW"),
None,
Some("DATAFUSION"),
Some("0123456789"),
Some(""),
])) as ArrayRef;
to_upper(input, expected)
}
#[test]
fn upper_partial_optimization() -> Result<()> {
let input = Arc::new(StringArray::from(vec![
Some("arrow"),
None,
Some("datafusion"),
Some("@_"),
Some("0123456789"),
Some(""),
Some("\t\n"),
Some("ὀδυσσεύς"),
Some("tschüß"),
Some("ⱦ"), Some("农历新年"),
])) as ArrayRef;
let expected = Arc::new(StringArray::from(vec![
Some("ARROW"),
None,
Some("DATAFUSION"),
Some("@_"),
Some("0123456789"),
Some(""),
Some("\t\n"),
Some("ὈΔΥΣΣΕΎΣ"),
Some("TSCHÜSS"),
Some("Ⱦ"),
Some("农历新年"),
])) as ArrayRef;
to_upper(input, expected)
}
}