datafusion_functions/string/
upper.rsuse crate::string::common::to_upper;
use crate::utils::utf8_to_str_type;
use arrow::datatypes::DataType;
use datafusion_common::Result;
use datafusion_expr::{ColumnarValue, Documentation};
use datafusion_expr::{ScalarUDFImpl, Signature, Volatility};
use datafusion_macros::user_doc;
use std::any::Any;
#[user_doc(
doc_section(label = "String Functions"),
description = "Converts a string to upper-case.",
syntax_example = "upper(str)",
sql_example = r#"```sql
> select upper('dataFusion');
+---------------------------+
| upper(Utf8("dataFusion")) |
+---------------------------+
| DATAFUSION |
+---------------------------+
```"#,
standard_argument(name = "str", prefix = "String"),
related_udf(name = "initcap"),
related_udf(name = "lower")
)]
#[derive(Debug)]
pub struct UpperFunc {
signature: Signature,
}
impl Default for UpperFunc {
fn default() -> Self {
Self::new()
}
}
impl UpperFunc {
pub fn new() -> Self {
Self {
signature: Signature::string(1, 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_batch(
&self,
args: &[ColumnarValue],
_number_rows: usize,
) -> Result<ColumnarValue> {
to_upper(args, "upper")
}
fn documentation(&self) -> Option<&Documentation> {
self.doc()
}
}
#[cfg(test)]
mod tests {
use super::*;
use arrow::array::{Array, ArrayRef, StringArray};
use std::sync::Arc;
fn to_upper(input: ArrayRef, expected: ArrayRef) -> Result<()> {
let func = UpperFunc::new();
let batch_len = input.len();
let args = vec![ColumnarValue::Array(input)];
#[allow(deprecated)] let result = match func.invoke_batch(&args, batch_len)? {
ColumnarValue::Array(result) => result,
_ => unreachable!("upper"),
};
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)
}
}