## Coverage Report

#### Created: 2025-11-22 06:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/datafusion/datafusion/functions/src/encoding/inner.rs

    Line
    Count
    Source
    1
    // Licensed to the Apache Software Foundation (ASF) under one
    2
    // or more contributor license agreements.  See the NOTICE file
    3
    // distributed with this work for additional information
    4
    // regarding copyright ownership.  The ASF licenses this file
    5
    // to you under the Apache License, Version 2.0 (the
    6
    // "License"); you may not use this file except in compliance
    7
    // with the License.  You may obtain a copy of the License at
    8
    //
    9
    //   http://www.apache.org/licenses/LICENSE-2.0
    10
    //
    11
    // Unless required by applicable law or agreed to in writing,
    12
    // software distributed under the License is distributed on an
    13
    // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14
    // KIND, either express or implied.  See the License for the
    15
    // specific language governing permissions and limitations
    16
    // under the License.
    17
    18
    //! Encoding expressions
    19
    20
    use arrow::{
    21
        array::{
    22
            Array, ArrayRef, BinaryArray, GenericByteArray, OffsetSizeTrait, StringArray,
    23
        },
    24
        datatypes::{ByteArrayType, DataType},
    25
    };
    26
    use arrow_buffer::{Buffer, OffsetBufferBuilder};
    27
    use base64::{
    28
        engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig},
    29
        Engine as _,
    30
    };
    31
    use datafusion_common::{
    32
        cast::{as_generic_binary_array, as_generic_string_array},
    33
        not_impl_err, plan_err,
    34
        utils::take_function_args,
    35
    };
    36
    use datafusion_common::{exec_err, internal_datafusion_err, ScalarValue};
    37
    use datafusion_common::{DataFusionError, Result};
    38
    use datafusion_expr::{ColumnarValue, Documentation};
    39
    use std::sync::Arc;
    40
    use std::{fmt, str::FromStr};
    41
    42
    use datafusion_expr::{ScalarUDFImpl, Signature, Volatility};
    43
    use datafusion_macros::user_doc;
    44
    use std::any::Any;
    45
    46
    // Allow padding characters, but don't require them, and don't generate them.
    47
    const BASE64_ENGINE: GeneralPurpose = GeneralPurpose::new(
    48
        &base64::alphabet::STANDARD,
    49
        GeneralPurposeConfig::new()
    50
            .with_encode_padding(false)
    51
            .with_decode_padding_mode(DecodePaddingMode::Indifferent),
    52
    );
    53
    54
    #[user_doc(
    55
        doc_section(label = "Binary String Functions"),
    56
        description = "Encode binary data into a textual representation.",
    57
        syntax_example = "encode(expression, format)",
    58
        argument(
    59
            name = "expression",
    60
            description = "Expression containing string or binary data"
    61
        ),
    62
        argument(
    63
            name = "format",
    64
            description = "Supported formats are: `base64`, `hex`"
    65
        ),
    66
        related_udf(name = "decode")
    67
    )]
    68
    #[derive(Debug, PartialEq, Eq, Hash)]
    69
    pub struct EncodeFunc {
    70
        signature: Signature,
    71
    }
    72
    73
    impl Default for EncodeFunc {
    74
    0
        fn default() -> Self {
    75
    0
            Self::new()
    76
    0
        }
    77
    }
    78
    79
    impl EncodeFunc {
    80
    0
        pub fn new() -> Self {
    81
    0
            Self {
    82
    0
                signature: Signature::user_defined(Volatility::Immutable),
    83
    0
            }
    84
    0
        }
    85
    }
    86
    87
    impl ScalarUDFImpl for EncodeFunc {
    88
    0
        fn as_any(&self) -> &dyn Any {
    89
    0
            self
    90
    0
        }
    91
    0
        fn name(&self) -> &str {
    92
    0
            "encode"
    93
    0
        }
    94
    95
    0
        fn signature(&self) -> &Signature {
    96
    0
            &self.signature
    97
    0
        }
    98
    99
    0
        fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
    100
            use DataType::*;
    101
    102
    0
            Ok(match arg_types[0] {
    103
    0
                Utf8 => Utf8,
    104
    0
                LargeUtf8 => LargeUtf8,
    105
    0
                Utf8View => Utf8,
    106
    0
                Binary => Utf8,
    107
    0
                LargeBinary => LargeUtf8,
    108
    0
                Null => Null,
    109
                _ => {
    110
    0
                    return plan_err!(
    111
    0
                        "The encode function can only accept Utf8 or Binary or Null."
    112
                    );
    113
                }
    114
            })
    115
    0
        }
    116
    117
    0
        fn invoke_with_args(
    118
    0
            &self,
    119
    0
            args: datafusion_expr::ScalarFunctionArgs,
    120
    0
        ) -> Result<ColumnarValue> {
    121
    0
            encode(&args.args)
    122
    0
        }
    123
    124
    0
        fn coerce_types(&self, arg_types: &[DataType]) -> Result<Vec<DataType>> {
    125
    0
            let [expression, format] = take_function_args(self.name(), arg_types)?;
    126
    127
    0
            if format != &DataType::Utf8 {
    128
    0
                return Err(DataFusionError::Plan("2nd argument should be Utf8".into()));
    129
    0
            }
    130
    131
    0
            match expression {
    132
                DataType::Utf8 | DataType::Utf8View | DataType::Null => {
    133
    0
                    Ok(vec![DataType::Utf8; 2])
    134
                }
    135
    0
                DataType::LargeUtf8 => Ok(vec![DataType::LargeUtf8, DataType::Utf8]),
    136
    0
                DataType::Binary => Ok(vec![DataType::Binary, DataType::Utf8]),
    137
    0
                DataType::LargeBinary => Ok(vec![DataType::LargeBinary, DataType::Utf8]),
    138
    0
                _ => plan_err!(
    139
    0
                    "1st argument should be Utf8 or Binary or Null, got {:?}",
    140
    0
                    arg_types[0]
    141
                ),
    142
            }
    143
    0
        }
    144
    145
    0
        fn documentation(&self) -> Option<&Documentation> {
    146
    0
            self.doc()
    147
    0
        }
    148
    }
    149
    150
    #[user_doc(
    151
        doc_section(label = "Binary String Functions"),
    152
        description = "Decode binary data from textual representation in string.",
    153
        syntax_example = "decode(expression, format)",
    154
        argument(
    155
            name = "expression",
    156
            description = "Expression containing encoded string data"
    157
        ),
    158
        argument(name = "format", description = "Same arguments as [encode](#encode)"),
    159
        related_udf(name = "encode")
    160
    )]
    161
    #[derive(Debug, PartialEq, Eq, Hash)]
    162
    pub struct DecodeFunc {
    163
        signature: Signature,
    164
    }
    165
    166
    impl Default for DecodeFunc {
    167
    0
        fn default() -> Self {
    168
    0
            Self::new()
    169
    0
        }
    170
    }
    171
    172
    impl DecodeFunc {
    173
    0
        pub fn new() -> Self {
    174
    0
            Self {
    175
    0
                signature: Signature::user_defined(Volatility::Immutable),
    176
    0
            }
    177
    0
        }
    178
    }
    179
    180
    impl ScalarUDFImpl for DecodeFunc {
    181
    0
        fn as_any(&self) -> &dyn Any {
    182
    0
            self
    183
    0
        }
    184
    0
        fn name(&self) -> &str {
    185
    0
            "decode"
    186
    0
        }
    187
    188
    0
        fn signature(&self) -> &Signature {
    189
    0
            &self.signature
    190
    0
        }
    191
    192
    0
        fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
    193
    0
            Ok(arg_types[0].to_owned())
    194
    0
        }
    195
    196
    0
        fn invoke_with_args(
    197
    0
            &self,
    198
    0
            args: datafusion_expr::ScalarFunctionArgs,
    199
    0
        ) -> Result<ColumnarValue> {
    200
    0
            decode(&args.args)
    201
    0
        }
    202
    203
    0
        fn coerce_types(&self, arg_types: &[DataType]) -> Result<Vec<DataType>> {
    204
    0
            if arg_types.len() != 2 {
    205
    0
                return plan_err!(
    206
    0
                    "{} expects to get 2 arguments, but got {}",
    207
    0
                    self.name(),
    208
    0
                    arg_types.len()
    209
                );
    210
    0
            }
    211
    212
    0
            if arg_types[1] != DataType::Utf8 {
    213
    0
                return plan_err!("2nd argument should be Utf8");
    214
    0
            }
    215
    216
    0
            match arg_types[0] {
    217
                DataType::Utf8 | DataType::Utf8View | DataType::Binary | DataType::Null => {
    218
    0
                    Ok(vec![DataType::Binary, DataType::Utf8])
    219
                }
    220
                DataType::LargeUtf8 | DataType::LargeBinary => {
    221
    0
                    Ok(vec![DataType::LargeBinary, DataType::Utf8])
    222
                }
    223
    0
                _ => plan_err!(
    224
    0
                    "1st argument should be Utf8 or Binary or Null, got {:?}",
    225
    0
                    arg_types[0]
    226
                ),
    227
            }
    228
    0
        }
    229
    230
    0
        fn documentation(&self) -> Option<&Documentation> {
    231
    0
            self.doc()
    232
    0
        }
    233
    }
    234
    235
    #[derive(Debug, Copy, Clone)]
    236
    enum Encoding {
    237
        Base64,
    238
        Hex,
    239
    }
    240
    241
    0
    fn encode_process(value: &ColumnarValue, encoding: Encoding) -> Result<ColumnarValue> {
    242
    0
        match value {
    243
    0
            ColumnarValue::Array(a) => match a.data_type() {
    244
    0
                DataType::Utf8 => encoding.encode_utf8_array::<i32>(a.as_ref()),
    245
    0
                DataType::LargeUtf8 => encoding.encode_utf8_array::<i64>(a.as_ref()),
    246
    0
                DataType::Utf8View => encoding.encode_utf8_array::<i32>(a.as_ref()),
    247
    0
                DataType::Binary => encoding.encode_binary_array::<i32>(a.as_ref()),
    248
    0
                DataType::LargeBinary => encoding.encode_binary_array::<i64>(a.as_ref()),
    249
    0
                other => exec_err!(
    250
    0
                    "Unsupported data type {other:?} for function encode({encoding})"
    251
                ),
    252
            },
    253
    0
            ColumnarValue::Scalar(scalar) => {
    254
    0
                match scalar {
    255
    0
                    ScalarValue::Utf8(a) => {
    256
    0
                        Ok(encoding.encode_scalar(a.as_ref().map(|s: &String| s.as_bytes())))
    257
                    }
    258
    0
                    ScalarValue::LargeUtf8(a) => Ok(encoding
    259
    0
                        .encode_large_scalar(a.as_ref().map(|s: &String| s.as_bytes()))),
    260
    0
                    ScalarValue::Utf8View(a) => {
    261
    0
                        Ok(encoding.encode_scalar(a.as_ref().map(|s: &String| s.as_bytes())))
    262
                    }
    263
    0
                    ScalarValue::Binary(a) => Ok(
    264
    0
                        encoding.encode_scalar(a.as_ref().map(|v: &Vec<u8>| v.as_slice()))
    265
                    ),
    266
    0
                    ScalarValue::LargeBinary(a) => Ok(encoding
    267
    0
                        .encode_large_scalar(a.as_ref().map(|v: &Vec<u8>| v.as_slice()))),
    268
    0
                    other => exec_err!(
    269
    0
                        "Unsupported data type {other:?} for function encode({encoding})"
    270
                    ),
    271
                }
    272
            }
    273
        }
    274
    0
    }
    275
    276
    0
    fn decode_process(value: &ColumnarValue, encoding: Encoding) -> Result<ColumnarValue> {
    277
    0
        match value {
    278
    0
            ColumnarValue::Array(a) => match a.data_type() {
    279
    0
                DataType::Utf8 => encoding.decode_utf8_array::<i32>(a.as_ref()),
    280
    0
                DataType::LargeUtf8 => encoding.decode_utf8_array::<i64>(a.as_ref()),
    281
    0
                DataType::Utf8View => encoding.decode_utf8_array::<i32>(a.as_ref()),
    282
    0
                DataType::Binary => encoding.decode_binary_array::<i32>(a.as_ref()),
    283
    0
                DataType::LargeBinary => encoding.decode_binary_array::<i64>(a.as_ref()),
    284
    0
                other => exec_err!(
    285
    0
                    "Unsupported data type {other:?} for function decode({encoding})"
    286
                ),
    287
            },
    288
    0
            ColumnarValue::Scalar(scalar) => {
    289
    0
                match scalar {
    290
    0
                    ScalarValue::Utf8(a) => {
    291
    0
                        encoding.decode_scalar(a.as_ref().map(|s: &String| s.as_bytes()))
    292
                    }
    293
    0
                    ScalarValue::LargeUtf8(a) => encoding
    294
    0
                        .decode_large_scalar(a.as_ref().map(|s: &String| s.as_bytes())),
    295
    0
                    ScalarValue::Utf8View(a) => {
    296
    0
                        encoding.decode_scalar(a.as_ref().map(|s: &String| s.as_bytes()))
    297
                    }
    298
    0
                    ScalarValue::Binary(a) => {
    299
    0
                        encoding.decode_scalar(a.as_ref().map(|v: &Vec<u8>| v.as_slice()))
    300
                    }
    301
    0
                    ScalarValue::LargeBinary(a) => encoding
    302
    0
                        .decode_large_scalar(a.as_ref().map(|v: &Vec<u8>| v.as_slice())),
    303
    0
                    other => exec_err!(
    304
    0
                        "Unsupported data type {other:?} for function decode({encoding})"
    305
                    ),
    306
                }
    307
            }
    308
        }
    309
    0
    }
    310
    311
    0
    fn hex_encode(input: &[u8]) -> String {
    312
    0
        hex::encode(input)
    313
    0
    }
    314
    315
    0
    fn base64_encode(input: &[u8]) -> String {
    316
    0
        BASE64_ENGINE.encode(input)
    317
    0
    }
    318
    319
    0
    fn hex_decode(input: &[u8], buf: &mut [u8]) -> Result<usize> {
    320
        // only write input / 2 bytes to buf
    321
    0
        let out_len = input.len() / 2;
    322
    0
        let buf = &mut buf[..out_len];
    323
    0
        hex::decode_to_slice(input, buf)
    324
    0
            .map_err(|e| internal_datafusion_err!("Failed to decode from hex: {e}"))?;
    325
    0
        Ok(out_len)
    326
    0
    }
    327
    328
    0
    fn base64_decode(input: &[u8], buf: &mut [u8]) -> Result<usize> {
    329
    0
        BASE64_ENGINE
    330
    0
            .decode_slice(input, buf)
    331
    0
            .map_err(|e| internal_datafusion_err!("Failed to decode from base64: {e}"))
    332
    0
    }
    333
    334
    macro_rules! encode_to_array {
    335
        ($METHOD: ident, $INPUT:expr) => {{
    336
            let utf8_array: StringArray = $INPUT
    337
                .iter()
    338
    0
                .map(|x| x.map(|x| $METHOD(x.as_ref())))
    339
                .collect();
    340
            Arc::new(utf8_array)
    341
        }};
    342
    }
    343
    344
    0
    fn decode_to_array<F, T: ByteArrayType>(
    345
    0
        method: F,
    346
    0
        input: &GenericByteArray<T>,
    347
    0
        conservative_upper_bound_size: usize,
    348
    0
    ) -> Result<ArrayRef>
    349
    0
    where
    350
    0
        F: Fn(&[u8], &mut [u8]) -> Result<usize>,
    351
    {
    352
    0
        let mut values = vec![0; conservative_upper_bound_size];
    353
    0
        let mut offsets = OffsetBufferBuilder::new(input.len());
    354
    0
        let mut total_bytes_decoded = 0;
    355
    0
        for v in input {
    356
    0
            if let Some(v) = v {
    357
    0
                let cursor = &mut values[total_bytes_decoded..];
    358
    0
                let decoded = method(v.as_ref(), cursor)?;
    359
    0
                total_bytes_decoded += decoded;
    360
    0
                offsets.push_length(decoded);
    361
    0
            } else {
    362
    0
                offsets.push_length(0);
    363
    0
            }
    364
        }
    365
        // We reserved an upper bound size for the values buffer, but we only use the actual size
    366
    0
        values.truncate(total_bytes_decoded);
    367
    0
        let binary_array = BinaryArray::try_new(
    368
    0
            offsets.finish(),
    369
    0
            Buffer::from_vec(values),
    370
    0
            input.nulls().cloned(),
    371
    0
        )?;
    372
    0
        Ok(Arc::new(binary_array))
    373
    0
    }
    374
    375
    impl Encoding {
    376
    0
        fn encode_scalar(self, value: Option<&[u8]>) -> ColumnarValue {
    377
    0
            ColumnarValue::Scalar(match self {
    378
    0
                Self::Base64 => ScalarValue::Utf8(value.map(|v| BASE64_ENGINE.encode(v))),
    379
    0
                Self::Hex => ScalarValue::Utf8(value.map(hex::encode)),
    380
            })
    381
    0
        }
    382
    383
    0
        fn encode_large_scalar(self, value: Option<&[u8]>) -> ColumnarValue {
    384
    0
            ColumnarValue::Scalar(match self {
    385
                Self::Base64 => {
    386
    0
                    ScalarValue::LargeUtf8(value.map(|v| BASE64_ENGINE.encode(v)))
    387
                }
    388
    0
                Self::Hex => ScalarValue::LargeUtf8(value.map(hex::encode)),
    389
            })
    390
    0
        }
    391
    392
    0
        fn encode_binary_array<T>(self, value: &dyn Array) -> Result<ColumnarValue>
    393
    0
        where
    394
    0
            T: OffsetSizeTrait,
    395
        {
    396
    0
            let input_value = as_generic_binary_array::<T>(value)?;
    397
    0
            let array: ArrayRef = match self {
    398
    0
                Self::Base64 => encode_to_array!(base64_encode, input_value),
    399
    0
                Self::Hex => encode_to_array!(hex_encode, input_value),
    400
            };
    401
    0
            Ok(ColumnarValue::Array(array))
    402
    0
        }
    403
    404
    0
        fn encode_utf8_array<T>(self, value: &dyn Array) -> Result<ColumnarValue>
    405
    0
        where
    406
    0
            T: OffsetSizeTrait,
    407
        {
    408
    0
            let input_value = as_generic_string_array::<T>(value)?;
    409
    0
            let array: ArrayRef = match self {
    410
    0
                Self::Base64 => encode_to_array!(base64_encode, input_value),
    411
    0
                Self::Hex => encode_to_array!(hex_encode, input_value),
    412
            };
    413
    0
            Ok(ColumnarValue::Array(array))
    414
    0
        }
    415
    416
    0
        fn decode_scalar(self, value: Option<&[u8]>) -> Result<ColumnarValue> {
    417
    0
            let value = match value {
    418
    0
                Some(value) => value,
    419
    0
                None => return Ok(ColumnarValue::Scalar(ScalarValue::Binary(None))),
    420
            };
    421
    422
    0
            let out = match self {
    423
    0
                Self::Base64 => BASE64_ENGINE.decode(value).map_err(|e| {
    424
    0
                    internal_datafusion_err!("Failed to decode value using base64: {e}")
    425
    0
                })?,
    426
    0
                Self::Hex => hex::decode(value).map_err(|e| {
    427
    0
                    internal_datafusion_err!("Failed to decode value using hex: {e}")
    428
    0
                })?,
    429
            };
    430
    431
    0
            Ok(ColumnarValue::Scalar(ScalarValue::Binary(Some(out))))
    432
    0
        }
    433
    434
    0
        fn decode_large_scalar(self, value: Option<&[u8]>) -> Result<ColumnarValue> {
    435
    0
            let value = match value {
    436
    0
                Some(value) => value,
    437
    0
                None => return Ok(ColumnarValue::Scalar(ScalarValue::LargeBinary(None))),
    438
            };
    439
    440
    0
            let out = match self {
    441
    0
                Self::Base64 => BASE64_ENGINE.decode(value).map_err(|e| {
    442
    0
                    internal_datafusion_err!("Failed to decode value using base64: {e}")
    443
    0
                })?,
    444
    0
                Self::Hex => hex::decode(value).map_err(|e| {
    445
    0
                    internal_datafusion_err!("Failed to decode value using hex: {e}")
    446
    0
                })?,
    447
            };
    448
    449
    0
            Ok(ColumnarValue::Scalar(ScalarValue::LargeBinary(Some(out))))
    450
    0
        }
    451
    452
    0
        fn decode_binary_array<T>(self, value: &dyn Array) -> Result<ColumnarValue>
    453
    0
        where
    454
    0
            T: OffsetSizeTrait,
    455
        {
    456
    0
            let input_value = as_generic_binary_array::<T>(value)?;
    457
    0
            let array = self.decode_byte_array(input_value)?;
    458
    0
            Ok(ColumnarValue::Array(array))
    459
    0
        }
    460
    461
    0
        fn decode_utf8_array<T>(self, value: &dyn Array) -> Result<ColumnarValue>
    462
    0
        where
    463
    0
            T: OffsetSizeTrait,
    464
        {
    465
    0
            let input_value = as_generic_string_array::<T>(value)?;
    466
    0
            let array = self.decode_byte_array(input_value)?;
    467
    0
            Ok(ColumnarValue::Array(array))
    468
    0
        }
    469
    470
    0
        fn decode_byte_array<T: ByteArrayType>(
    471
    0
            &self,
    472
    0
            input_value: &GenericByteArray<T>,
    473
    0
        ) -> Result<ArrayRef> {
    474
    0
            match self {
    475
                Self::Base64 => {
    476
    0
                    let upper_bound =
    477
    0
                        base64::decoded_len_estimate(input_value.values().len());
    478
    0
                    decode_to_array(base64_decode, input_value, upper_bound)
    479
                }
    480
                Self::Hex => {
    481
                    // Calculate the upper bound for decoded byte size
    482
                    // For hex encoding, each pair of hex characters (2 bytes) represents 1 byte when decoded
    483
                    // So the upper bound is half the length of the input values.
    484
    0
                    let upper_bound = input_value.values().len() / 2;
    485
    0
                    decode_to_array(hex_decode, input_value, upper_bound)
    486
                }
    487
            }
    488
    0
        }
    489
    }
    490
    491
    impl fmt::Display for Encoding {
    492
    0
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    493
    0
            write!(f, "{}", format!("{self:?}").to_lowercase())
    494
    0
        }
    495
    }
    496
    497
    impl FromStr for Encoding {
    498
        type Err = DataFusionError;
    499
    0
        fn from_str(name: &str) -> Result<Encoding> {
    500
    0
            Ok(match name {
    501
    0
                "base64" => Self::Base64,
    502
    0
                "hex" => Self::Hex,
    503
                _ => {
    504
    0
                    let options = [Self::Base64, Self::Hex]
    505
    0
                        .iter()
    506
    0
                        .map(|i| i.to_string())
    507
    0
                        .collect::<Vec<_>>()
    508
    0
                        .join(", ");
    509
    0
                    return plan_err!(
    510
    0
                        "There is no built-in encoding named '{name}', currently supported encodings are: {options}"
    511
                    );
    512
                }
    513
            })
    514
    0
        }
    515
    }
    516
    517
    /// Encodes the given data, accepts Binary, LargeBinary, Utf8, Utf8View or LargeUtf8 and returns a [`ColumnarValue`].
    518
    /// Second argument is the encoding to use.
    519
    /// Standard encodings are base64 and hex.
    520
    0
    fn encode(args: &[ColumnarValue]) -> Result<ColumnarValue> {
    521
    0
        let [expression, format] = take_function_args("encode", args)?;
    522
    523
    0
        let encoding = match format {
    524
    0
            ColumnarValue::Scalar(scalar) => match scalar.try_as_str() {
    525
    0
                Some(Some(method)) => method.parse::<Encoding>(),
    526
    0
                _ => not_impl_err!(
    527
    0
                    "Second argument to encode must be non null constant string: Encode using dynamically decided method is not yet supported. Got {scalar:?}"
    528
                ),
    529
            },
    530
    0
            ColumnarValue::Array(_) => not_impl_err!(
    531
    0
                "Second argument to encode must be a constant: Encode using dynamically decided method is not yet supported"
    532
            ),
    533
    0
        }?;
    534
    0
        encode_process(expression, encoding)
    535
    0
    }
    536
    537
    /// Decodes the given data, accepts Binary, LargeBinary, Utf8, Utf8View or LargeUtf8 and returns a [`ColumnarValue`].
    538
    /// Second argument is the encoding to use.
    539
    /// Standard encodings are base64 and hex.
    540
    0
    fn decode(args: &[ColumnarValue]) -> Result<ColumnarValue> {
    541
    0
        let [expression, format] = take_function_args("decode", args)?;
    542
    543
    0
        let encoding = match format {
    544
    0
            ColumnarValue::Scalar(scalar) => match scalar.try_as_str() {
    545
    0
                Some(Some(method))=> method.parse::<Encoding>(),
    546
    0
                _ => not_impl_err!(
    547
    0
                    "Second argument to decode must be a non null constant string: Decode using dynamically decided method is not yet supported. Got {scalar:?}"
    548
                ),
    549
            },
    550
    0
            ColumnarValue::Array(_) => not_impl_err!(
    551
    0
                "Second argument to decode must be a utf8 constant: Decode using dynamically decided method is not yet supported"
    552
            ),
    553
    0
        }?;
    554
    0
        decode_process(expression, encoding)
    555
    0
    }