Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Added cast for FixedSizeBinary to (Large)Binary #1403

Merged
merged 2 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/array/fixed_size_binary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ impl FixedSizeBinaryArray {

// must use
impl FixedSizeBinaryArray {
/// Retrieve the size of the binary elements
/// in this ['FixedSizeBinaryArray']
pub fn fixed_size(&self) -> usize {
ritchie46 marked this conversation as resolved.
Show resolved Hide resolved
self.size
}

/// Slices this [`FixedSizeBinaryArray`].
/// # Implementation
/// This operation is `O(1)`.
Expand Down
43 changes: 42 additions & 1 deletion src/compute/cast/binary_to.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::error::Result;
use crate::offset::Offset;
use crate::offset::{Offset, Offsets};
use crate::{array::*, datatypes::DataType, types::NativeType};

use super::CastOptions;
Expand Down Expand Up @@ -118,3 +118,44 @@ pub(super) fn binary_to_dictionary_dyn<O: Offset, K: DictionaryKey>(
let values = from.as_any().downcast_ref().unwrap();
binary_to_dictionary::<O, K>(values).map(|x| Box::new(x) as Box<dyn Array>)
}

fn fixed_size_to_offsets<O: Offset>(values_len: usize, fixed_size: usize) -> Offsets<O> {
let offsets = (0..(values_len + 1))
.step_by(fixed_size)
.map(|v| O::from_usize(v).unwrap())
.collect();
// Safety
// * every element is `>= 0`
// * element at position `i` is >= than element at position `i-1`.
unsafe { Offsets::new_unchecked(offsets) }
}

/// Conversion of large-binary
pub fn fixed_size_binary_to_large_binary(
ritchie46 marked this conversation as resolved.
Show resolved Hide resolved
from: &FixedSizeBinaryArray,
to_data_type: DataType,
) -> BinaryArray<i64> {
let values = from.values().clone();
let offsets = fixed_size_to_offsets(values.len(), from.fixed_size());
ritchie46 marked this conversation as resolved.
Show resolved Hide resolved
BinaryArray::<i64>::new(
to_data_type,
offsets.into(),
values,
from.validity().cloned(),
)
}

/// Conversion of binary
pub fn fixed_size_binary_to_binary(
from: &FixedSizeBinaryArray,
to_data_type: DataType,
) -> BinaryArray<i32> {
let values = from.values().clone();
let offsets = fixed_size_to_offsets(values.len(), from.fixed_size());
ritchie46 marked this conversation as resolved.
Show resolved Hide resolved
BinaryArray::<i32>::new(
to_data_type,
offsets.into(),
values,
from.validity().cloned(),
)
}
17 changes: 16 additions & 1 deletion src/compute/cast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
is_numeric(to_type) || matches!(to_type, LargeBinary | Utf8 | LargeUtf8)
}
(LargeBinary, to_type) => is_numeric(to_type) || matches!(to_type, Binary | LargeUtf8),

(FixedSizeBinary(_), to_type) => matches!(to_type, Binary | LargeBinary),
(Timestamp(_, _), Utf8) => true,
(Timestamp(_, _), LargeUtf8) => true,
(_, Utf8) => is_numeric(from_type) || from_type == &Binary,
Expand Down Expand Up @@ -686,6 +686,21 @@ pub fn cast(array: &dyn Array, to_type: &DataType, options: CastOptions) -> Resu
"Casting from {from_type:?} to {to_type:?} not supported",
))),
},
(FixedSizeBinary(_), _) => match to_type {
Binary => Ok(fixed_size_binary_to_binary(
array.as_any().downcast_ref().unwrap(),
to_type.clone(),
)
.boxed()),
LargeBinary => Ok(fixed_size_binary_to_large_binary(
array.as_any().downcast_ref().unwrap(),
to_type.clone(),
)
.boxed()),
_ => Err(Error::NotYetImplemented(format!(
"Casting from {from_type:?} to {to_type:?} not supported",
))),
},

(_, Binary) => match from_type {
UInt8 => primitive_to_binary_dyn::<u8, i32>(array),
Expand Down
32 changes: 32 additions & 0 deletions tests/it/compute/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,38 @@ fn binary_to_i32_partial() {
assert_eq!(c, &expected);
}

#[test]
fn fixed_size_binary_to_binary() {
let slice = [[0, 1], [2, 3]];
let array = FixedSizeBinaryArray::from_slice(slice);

// large-binary
let b = cast(
&array,
&DataType::LargeBinary,
CastOptions {
..Default::default()
},
)
.unwrap();
let c = b.as_any().downcast_ref::<BinaryArray<i64>>().unwrap();
let expected = BinaryArray::<i64>::from_slice(slice);
assert_eq!(c, &expected);

// binary
let b = cast(
&array,
&DataType::Binary,
CastOptions {
..Default::default()
},
)
.unwrap();
let c = b.as_any().downcast_ref::<BinaryArray<i32>>().unwrap();
let expected = BinaryArray::<i32>::from_slice(slice);
assert_eq!(c, &expected);
}

#[test]
fn utf8_to_i32() {
let array = Utf8Array::<i32>::from_slice(["5", "6", "seven", "8", "9.1"]);
Expand Down