-
Notifications
You must be signed in to change notification settings - Fork 841
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add downcast macros (#2635) #2636
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,213 @@ | |
use crate::array::*; | ||
use crate::datatypes::*; | ||
|
||
/// Downcast an [`Array`] to a [`PrimitiveArray`] based on its [`DataType`], accepts | ||
/// a number of subsequent patterns to match the data type | ||
/// | ||
/// ``` | ||
/// # use arrow::downcast_primitive_array; | ||
/// # use arrow::array::Array; | ||
/// # use arrow::datatypes::DataType; | ||
/// # use arrow::array::as_string_array; | ||
/// | ||
/// fn print_primitive(array: &dyn Array) { | ||
/// downcast_primitive_array!( | ||
/// array => { | ||
/// for v in array { | ||
/// println!("{:?}", v); | ||
/// } | ||
/// } | ||
/// DataType::Utf8 => { | ||
/// for v in as_string_array(array) { | ||
/// println!("{:?}", v); | ||
/// } | ||
/// } | ||
/// t => println!("Unsupported datatype {}", t) | ||
/// ) | ||
/// } | ||
/// ``` | ||
/// | ||
#[macro_export] | ||
macro_rules! downcast_primitive_array { | ||
($values:ident => $e:expr, $($p:pat => $fallback:expr $(,)*)*) => { | ||
downcast_primitive_array!($values => {$e} $($p => $fallback)*) | ||
}; | ||
|
||
($values:ident => $e:block $($p:pat => $fallback:expr $(,)*)*) => { | ||
match $values.data_type() { | ||
$crate::datatypes::DataType::Int8 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Int8Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Int16 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Int16Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Int32 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Int32Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Int64 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Int64Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::UInt8 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::UInt8Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::UInt16 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::UInt16Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::UInt32 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::UInt32Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::UInt64 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::UInt64Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Float16 => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was actually missing before |
||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Float16Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Float32 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Float32Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Float64 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Float64Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Date32 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Date32Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Date64 => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Date64Type, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Time32($crate::datatypes::TimeUnit::Second) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Time32SecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Time32($crate::datatypes::TimeUnit::Millisecond) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Time32MillisecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Time64($crate::datatypes::TimeUnit::Microsecond) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Time64MicrosecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Time64($crate::datatypes::TimeUnit::Nanosecond) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::Time64NanosecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Timestamp($crate::datatypes::TimeUnit::Second, _) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::TimestampSecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Timestamp($crate::datatypes::TimeUnit::Millisecond, _) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::TimestampMillisecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Timestamp($crate::datatypes::TimeUnit::Microsecond, _) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::TimestampMicrosecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Timestamp($crate::datatypes::TimeUnit::Nanosecond, _) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::TimestampNanosecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Interval($crate::datatypes::IntervalUnit::YearMonth) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::IntervalYearMonthType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Interval($crate::datatypes::IntervalUnit::DayTime) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::IntervalDayTimeType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Interval($crate::datatypes::IntervalUnit::MonthDayNano) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::IntervalMonthDayNanoType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Duration($crate::datatypes::TimeUnit::Second) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::DurationSecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Duration($crate::datatypes::TimeUnit::Millisecond) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::DurationMillisecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Duration($crate::datatypes::TimeUnit::Microsecond) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::DurationMicrosecondType, | ||
>($values); | ||
$e | ||
} | ||
$crate::datatypes::DataType::Duration($crate::datatypes::TimeUnit::Nanosecond) => { | ||
let $values = $crate::array::as_primitive_array::< | ||
$crate::datatypes::DurationNanosecondType, | ||
>($values); | ||
$e | ||
} | ||
$($p => $fallback,)* | ||
} | ||
}; | ||
} | ||
|
||
/// Force downcast of an [`Array`], such as an [`ArrayRef`], to | ||
/// [`PrimitiveArray<T>`], panic'ing on failure. | ||
/// | ||
|
@@ -53,6 +260,98 @@ where | |
.expect("Unable to downcast to primitive array") | ||
} | ||
|
||
/// Downcast an [`Array`] to a [`DictionaryArray`] based on its [`DataType`], accepts | ||
/// a number of subsequent patterns to match the data type | ||
/// | ||
/// ``` | ||
/// # use arrow::downcast_dictionary_array; | ||
/// # use arrow::array::{Array, StringArray}; | ||
/// # use arrow::datatypes::DataType; | ||
/// # use arrow::array::as_string_array; | ||
/// | ||
/// fn print_strings(array: &dyn Array) { | ||
/// downcast_dictionary_array!( | ||
/// array => match array.values().data_type() { | ||
/// DataType::Utf8 => { | ||
/// for v in array.downcast_dict::<StringArray>().unwrap() { | ||
/// println!("{:?}", v); | ||
/// } | ||
/// } | ||
/// t => println!("Unsupported dictionary value type {}", t), | ||
/// }, | ||
/// DataType::Utf8 => { | ||
/// for v in as_string_array(array) { | ||
/// println!("{:?}", v); | ||
/// } | ||
/// } | ||
/// t => println!("Unsupported datatype {}", t) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be good to extend this example to show the String array as well -- not only to document how to support other types, but also because the StringArray is so common There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, and threw in a bit of TypedDictionaryArray spice as well 😆 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🥘 👍 |
||
/// ) | ||
/// } | ||
/// ``` | ||
#[macro_export] | ||
macro_rules! downcast_dictionary_array { | ||
($values:ident => $e:expr, $($p:pat => $fallback:expr $(,)*)*) => { | ||
downcast_dictionary_array!($values => {$e} $($p => $fallback)*) | ||
}; | ||
|
||
($values:ident => $e:block $($p:pat => $fallback:expr $(,)*)*) => { | ||
match $values.data_type() { | ||
$crate::datatypes::DataType::Dictionary(k, _) => match k.as_ref() { | ||
$crate::datatypes::DataType::Int8 => { | ||
let $values = $crate::array::as_dictionary_array::< | ||
$crate::datatypes::Int8Type, | ||
>($values); | ||
$e | ||
}, | ||
$crate::datatypes::DataType::Int16 => { | ||
let $values = $crate::array::as_dictionary_array::< | ||
$crate::datatypes::Int16Type, | ||
>($values); | ||
$e | ||
}, | ||
$crate::datatypes::DataType::Int32 => { | ||
let $values = $crate::array::as_dictionary_array::< | ||
$crate::datatypes::Int32Type, | ||
>($values); | ||
$e | ||
}, | ||
$crate::datatypes::DataType::Int64 => { | ||
let $values = $crate::array::as_dictionary_array::< | ||
$crate::datatypes::Int64Type, | ||
>($values); | ||
$e | ||
}, | ||
$crate::datatypes::DataType::UInt8 => { | ||
let $values = $crate::array::as_dictionary_array::< | ||
$crate::datatypes::UInt8Type, | ||
>($values); | ||
$e | ||
}, | ||
$crate::datatypes::DataType::UInt16 => { | ||
let $values = $crate::array::as_dictionary_array::< | ||
$crate::datatypes::UInt16Type, | ||
>($values); | ||
$e | ||
}, | ||
$crate::datatypes::DataType::UInt32 => { | ||
let $values = $crate::array::as_dictionary_array::< | ||
$crate::datatypes::UInt32Type, | ||
>($values); | ||
$e | ||
}, | ||
$crate::datatypes::DataType::UInt64 => { | ||
let $values = $crate::array::as_dictionary_array::< | ||
$crate::datatypes::UInt64Type, | ||
>($values); | ||
$e | ||
}, | ||
k => unreachable!("unsupported dictionary key type: {}", k) | ||
} | ||
$($p => $fallback,)* | ||
} | ||
} | ||
} | ||
|
||
/// Force downcast of an [`Array`], such as an [`ArrayRef`] to | ||
/// [`DictionaryArray<T>`], panic'ing on failure. | ||
/// | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️ that certainly will make the macros in code such as https://github.com/apache/arrow-datafusion/blob/master/datafusion/physical-expr/src/expressions/binary.rs easier to deal with ❤️