datafusion_functions/string/
bit_length.rs1use arrow::compute::kernels::length::bit_length;
19use arrow::datatypes::DataType;
20use std::any::Any;
21
22use crate::utils::utf8_to_int_type;
23use datafusion_common::types::logical_string;
24use datafusion_common::utils::take_function_args;
25use datafusion_common::{Result, ScalarValue};
26use datafusion_expr::{
27 Coercion, ColumnarValue, Documentation, ScalarFunctionArgs, ScalarUDFImpl, Signature,
28 TypeSignatureClass, Volatility,
29};
30use datafusion_macros::user_doc;
31
32#[user_doc(
33 doc_section(label = "String Functions"),
34 description = "Returns the bit length of a string.",
35 syntax_example = "bit_length(str)",
36 sql_example = r#"```sql
37> select bit_length('datafusion');
38+--------------------------------+
39| bit_length(Utf8("datafusion")) |
40+--------------------------------+
41| 80 |
42+--------------------------------+
43```"#,
44 standard_argument(name = "str", prefix = "String"),
45 related_udf(name = "length"),
46 related_udf(name = "octet_length")
47)]
48#[derive(Debug)]
49pub struct BitLengthFunc {
50 signature: Signature,
51}
52
53impl Default for BitLengthFunc {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl BitLengthFunc {
60 pub fn new() -> Self {
61 Self {
62 signature: Signature::coercible(
63 vec![Coercion::new_exact(TypeSignatureClass::Native(
64 logical_string(),
65 ))],
66 Volatility::Immutable,
67 ),
68 }
69 }
70}
71
72impl ScalarUDFImpl for BitLengthFunc {
73 fn as_any(&self) -> &dyn Any {
74 self
75 }
76
77 fn name(&self) -> &str {
78 "bit_length"
79 }
80
81 fn signature(&self) -> &Signature {
82 &self.signature
83 }
84
85 fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
86 utf8_to_int_type(&arg_types[0], "bit_length")
87 }
88
89 fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
90 let [array] = take_function_args(self.name(), &args.args)?;
91
92 match array {
93 ColumnarValue::Array(v) => Ok(ColumnarValue::Array(bit_length(v.as_ref())?)),
94 ColumnarValue::Scalar(v) => match v {
95 ScalarValue::Utf8(v) => Ok(ColumnarValue::Scalar(ScalarValue::Int32(
96 v.as_ref().map(|x| (x.len() * 8) as i32),
97 ))),
98 ScalarValue::LargeUtf8(v) => Ok(ColumnarValue::Scalar(
99 ScalarValue::Int64(v.as_ref().map(|x| (x.len() * 8) as i64)),
100 )),
101 ScalarValue::Utf8View(v) => Ok(ColumnarValue::Scalar(
102 ScalarValue::Int32(v.as_ref().map(|x| (x.len() * 8) as i32)),
103 )),
104 _ => unreachable!("bit length"),
105 },
106 }
107 }
108
109 fn documentation(&self) -> Option<&Documentation> {
110 self.doc()
111 }
112}