diff --git a/encodings/alp/public-api.lock b/encodings/alp/public-api.lock index b4dcad31098..263eb03207f 100644 --- a/encodings/alp/public-api.lock +++ b/encodings/alp/public-api.lock @@ -80,7 +80,7 @@ pub fn vortex_alp::ALP::compare(lhs: vortex_array::array::view::ArrayView<'_, Se impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_alp::ALP -pub fn vortex_alp::ALP::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_alp::ALP::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::kernel::MaskKernel for vortex_alp::ALP @@ -208,7 +208,7 @@ pub fn vortex_alp::ALPRD::slice(array: vortex_array::array::view::ArrayView<'_, impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_alp::ALPRD -pub fn vortex_alp::ALPRD::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_alp::ALPRD::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::kernel::MaskReduce for vortex_alp::ALPRD diff --git a/encodings/alp/src/alp/compute/cast.rs b/encodings/alp/src/alp/compute/cast.rs index 99eaa09ff2c..0e6473c5736 100644 --- a/encodings/alp/src/alp/compute/cast.rs +++ b/encodings/alp/src/alp/compute/cast.rs @@ -7,6 +7,7 @@ use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; use vortex_array::patches::Patches; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; @@ -15,16 +16,21 @@ use crate::ALPArraySlotsExt; use crate::alp::ALP; impl CastReduce for ALP { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // Check if this is just a nullability change if array.dtype().eq_ignore_nullability(dtype) { // For nullability-only changes, we can avoid decoding // Cast the encoded array (integers) to handle nullability - let new_encoded = array.encoded().cast( + let new_encoded = array.encoded().cast_opts( array .encoded() .dtype() .with_nullability(dtype.nullability()), + *options, )?; let new_patches = array @@ -37,7 +43,7 @@ impl CastReduce for ALP { p.array_len(), p.offset(), p.indices().clone(), - p.values().cast(dtype.clone())?, + p.values().cast_opts(dtype.clone(), *options)?, p.chunk_offsets().clone(), ) } diff --git a/encodings/alp/src/alp_rd/compute/cast.rs b/encodings/alp/src/alp_rd/compute/cast.rs index 69d3252ba89..4ecc2a00841 100644 --- a/encodings/alp/src/alp_rd/compute/cast.rs +++ b/encodings/alp/src/alp_rd/compute/cast.rs @@ -6,6 +6,7 @@ use vortex_array::ArrayView; use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; @@ -13,7 +14,11 @@ use crate::ALPRDArrayExt; use crate::alp_rd::ALPRD; impl CastReduce for ALPRD { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // ALPRDArray stores floating-point values, so only cast between float types // or if just changing nullability @@ -21,11 +26,12 @@ impl CastReduce for ALPRD { if array.dtype().eq_ignore_nullability(dtype) { // For nullability-only changes, we need to cast the left_parts array // since it carries the validity information - let new_left_parts = array.left_parts().cast( + let new_left_parts = array.left_parts().cast_opts( array .left_parts() .dtype() .with_nullability(dtype.nullability()), + *options, )?; return Ok(Some( diff --git a/encodings/bytebool/public-api.lock b/encodings/bytebool/public-api.lock index 53c71e3bfb6..ec781082953 100644 --- a/encodings/bytebool/public-api.lock +++ b/encodings/bytebool/public-api.lock @@ -66,7 +66,7 @@ pub fn vortex_bytebool::ByteBool::slice(array: vortex_array::array::view::ArrayV impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_bytebool::ByteBool -pub fn vortex_bytebool::ByteBool::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_bytebool::ByteBool::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::kernel::MaskReduce for vortex_bytebool::ByteBool diff --git a/encodings/bytebool/src/compute.rs b/encodings/bytebool/src/compute.rs index 609a7bc553f..6f31ad0218c 100644 --- a/encodings/bytebool/src/compute.rs +++ b/encodings/bytebool/src/compute.rs @@ -11,6 +11,7 @@ use vortex_array::arrays::dict::TakeExecute; use vortex_array::buffer::BufferHandle; use vortex_array::dtype::DType; use vortex_array::match_each_integer_ptype; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_array::scalar_fn::fns::mask::MaskReduce; use vortex_array::validity::Validity; @@ -20,7 +21,11 @@ use vortex_error::VortexResult; use super::ByteBool; impl CastReduce for ByteBool { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + _options: &CastOptions, + ) -> VortexResult> { // ByteBool is essentially a bool array stored as bytes // The main difference from BoolArray is the storage format // For casting, we can decode to canonical (BoolArray) and let it handle the cast diff --git a/encodings/datetime-parts/public-api.lock b/encodings/datetime-parts/public-api.lock index e5935cf15a8..1995a0196cb 100644 --- a/encodings/datetime-parts/public-api.lock +++ b/encodings/datetime-parts/public-api.lock @@ -72,7 +72,7 @@ pub fn vortex_datetime_parts::DateTimeParts::compare(lhs: vortex_array::array::v impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_datetime_parts::DateTimeParts -pub fn vortex_datetime_parts::DateTimeParts::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_datetime_parts::DateTimeParts::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::kernel::MaskReduce for vortex_datetime_parts::DateTimeParts diff --git a/encodings/datetime-parts/src/compute/cast.rs b/encodings/datetime-parts/src/compute/cast.rs index 573a0af48d7..49f048ca0af 100644 --- a/encodings/datetime-parts/src/compute/cast.rs +++ b/encodings/datetime-parts/src/compute/cast.rs @@ -6,13 +6,18 @@ use vortex_array::ArrayView; use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use crate::DateTimeParts; use crate::array::DateTimePartsArrayExt; impl CastReduce for DateTimeParts { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { if !array.dtype().eq_ignore_nullability(dtype) { return Ok(None); }; @@ -20,9 +25,10 @@ impl CastReduce for DateTimeParts { Ok(Some( DateTimeParts::try_new( dtype.clone(), - array - .days() - .cast(array.days().dtype().with_nullability(dtype.nullability()))?, + array.days().cast_opts( + array.days().dtype().with_nullability(dtype.nullability()), + *options, + )?, array.seconds().clone(), array.subseconds().clone(), )? diff --git a/encodings/decimal-byte-parts/public-api.lock b/encodings/decimal-byte-parts/public-api.lock index 4c4162b1f92..66d05f6cb16 100644 --- a/encodings/decimal-byte-parts/public-api.lock +++ b/encodings/decimal-byte-parts/public-api.lock @@ -70,7 +70,7 @@ pub fn vortex_decimal_byte_parts::DecimalByteParts::compare(lhs: vortex_array::a impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_decimal_byte_parts::DecimalByteParts -pub fn vortex_decimal_byte_parts::DecimalByteParts::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_decimal_byte_parts::DecimalByteParts::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::kernel::MaskReduce for vortex_decimal_byte_parts::DecimalByteParts diff --git a/encodings/decimal-byte-parts/src/decimal_byte_parts/compute/cast.rs b/encodings/decimal-byte-parts/src/decimal_byte_parts/compute/cast.rs index 30d7bcd9a5f..0bc29f36052 100644 --- a/encodings/decimal-byte-parts/src/decimal_byte_parts/compute/cast.rs +++ b/encodings/decimal-byte-parts/src/decimal_byte_parts/compute/cast.rs @@ -6,6 +6,7 @@ use vortex_array::ArrayView; use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexExpect; use vortex_error::VortexResult; @@ -13,7 +14,11 @@ use vortex_error::VortexResult; use crate::DecimalByteParts; use crate::decimal_byte_parts::DecimalBytePartsArrayExt; impl CastReduce for DecimalByteParts { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // DecimalBytePartsArray can only have Decimal dtype, so we only handle decimal-to-decimal casts let DType::Decimal(target_decimal, target_nullability) = dtype else { // Cannot cast decimal to non-decimal types - delegate to canonical form @@ -29,9 +34,10 @@ impl CastReduce for DecimalByteParts { && array.dtype().nullability() != *target_nullability { // Cast the msp array to handle nullability change - let new_msp = array - .msp() - .cast(array.msp().dtype().with_nullability(*target_nullability))?; + let new_msp = array.msp().cast_opts( + array.msp().dtype().with_nullability(*target_nullability), + *options, + )?; return Ok(Some( DecimalByteParts::try_new(new_msp, *target_decimal)?.into_array(), diff --git a/encodings/fastlanes/public-api.lock b/encodings/fastlanes/public-api.lock index 4f8e8f67cfe..d632e326195 100644 --- a/encodings/fastlanes/public-api.lock +++ b/encodings/fastlanes/public-api.lock @@ -188,7 +188,7 @@ pub fn vortex_fastlanes::BitPacked::slice(array: vortex_array::array::view::Arra impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_fastlanes::BitPacked -pub fn vortex_fastlanes::BitPacked::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_fastlanes::BitPacked::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> pub struct vortex_fastlanes::BitPackedData @@ -332,7 +332,7 @@ pub fn vortex_fastlanes::Delta::slice(array: vortex_array::array::view::ArrayVie impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_fastlanes::Delta -pub fn vortex_fastlanes::Delta::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_fastlanes::Delta::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> pub struct vortex_fastlanes::DeltaData @@ -432,7 +432,7 @@ pub fn vortex_fastlanes::FoR::compare(lhs: vortex_array::array::view::ArrayView< impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_fastlanes::FoR -pub fn vortex_fastlanes::FoR::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_fastlanes::FoR::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> pub struct vortex_fastlanes::FoRData @@ -526,7 +526,7 @@ pub fn vortex_fastlanes::RLE::slice(array: vortex_array::array::view::ArrayView< impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_fastlanes::RLE -pub fn vortex_fastlanes::RLE::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_fastlanes::RLE::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> pub struct vortex_fastlanes::RLEData diff --git a/encodings/fastlanes/src/bitpacking/compute/cast.rs b/encodings/fastlanes/src/bitpacking/compute/cast.rs index fbcd48ce75b..ee15c7743e8 100644 --- a/encodings/fastlanes/src/bitpacking/compute/cast.rs +++ b/encodings/fastlanes/src/bitpacking/compute/cast.rs @@ -7,13 +7,18 @@ use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; use vortex_array::patches::Patches; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use crate::bitpacking::BitPacked; use crate::bitpacking::array::BitPackedArrayExt; impl CastReduce for BitPacked { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { if array.dtype().eq_ignore_nullability(dtype) { let new_validity = array .validity()? @@ -26,7 +31,7 @@ impl CastReduce for BitPacked { array .patches() .map(|patches| { - let new_values = patches.values().cast(dtype.clone())?; + let new_values = patches.values().cast_opts(dtype.clone(), *options)?; Patches::new( patches.array_len(), patches.offset(), diff --git a/encodings/fastlanes/src/delta/compute/cast.rs b/encodings/fastlanes/src/delta/compute/cast.rs index 4beb558dca0..220b29594d5 100644 --- a/encodings/fastlanes/src/delta/compute/cast.rs +++ b/encodings/fastlanes/src/delta/compute/cast.rs @@ -7,6 +7,7 @@ use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; use vortex_array::dtype::Nullability::NonNullable; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use vortex_error::vortex_panic; @@ -14,7 +15,11 @@ use vortex_error::vortex_panic; use crate::delta::Delta; use crate::delta::array::DeltaArrayExt; impl CastReduce for Delta { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // Delta encoding stores differences between consecutive values, which requires // unsigned integers to avoid overflow issues. Signed integers could produce // negative deltas that wouldn't fit in the unsigned delta representation. @@ -33,8 +38,10 @@ impl CastReduce for Delta { } // Cast both bases and deltas to the target type - let casted_bases = array.bases().cast(dtype.with_nullability(NonNullable))?; - let casted_deltas = array.deltas().cast(dtype.clone())?; + let casted_bases = array + .bases() + .cast_opts(dtype.with_nullability(NonNullable), *options)?; + let casted_deltas = array.deltas().cast_opts(dtype.clone(), *options)?; // Create a new DeltaArray with the casted components, preserving offset and logical length Ok(Some( diff --git a/encodings/fastlanes/src/for/compute/cast.rs b/encodings/fastlanes/src/for/compute/cast.rs index e534f3c76fa..34458586832 100644 --- a/encodings/fastlanes/src/for/compute/cast.rs +++ b/encodings/fastlanes/src/for/compute/cast.rs @@ -6,20 +6,25 @@ use vortex_array::ArrayView; use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use crate::r#for::FoR; use crate::r#for::array::FoRArrayExt; impl CastReduce for FoR { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // FoR only supports integer types if !dtype.is_int() { return Ok(None); } // For type changes between integers, cast the components - let casted_child = array.encoded().cast(dtype.clone())?; + let casted_child = array.encoded().cast_opts(dtype.clone(), *options)?; let casted_reference = array.reference_scalar().cast(dtype)?; Ok(Some( diff --git a/encodings/fastlanes/src/rle/compute/cast.rs b/encodings/fastlanes/src/rle/compute/cast.rs index fc63f293c3a..5e2af11926c 100644 --- a/encodings/fastlanes/src/rle/compute/cast.rs +++ b/encodings/fastlanes/src/rle/compute/cast.rs @@ -7,24 +7,30 @@ use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; use vortex_array::dtype::Nullability; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use crate::rle::RLE; use crate::rle::RLEArrayExt; impl CastReduce for RLE { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // Cast RLE values. - let casted_values = array - .values() - .cast(DType::Primitive(dtype.as_ptype(), Nullability::NonNullable))?; + let casted_values = array.values().cast_opts( + DType::Primitive(dtype.as_ptype(), Nullability::NonNullable), + *options, + )?; // Cast RLE indices such that validity matches the target dtype. let casted_indices = if array.indices().dtype().nullability() != dtype.nullability() { - array.indices().cast(DType::Primitive( - array.indices().dtype().as_ptype(), - dtype.nullability(), - ))? + array.indices().cast_opts( + DType::Primitive(array.indices().dtype().as_ptype(), dtype.nullability()), + *options, + )? } else { array.indices().clone() }; diff --git a/encodings/fsst/public-api.lock b/encodings/fsst/public-api.lock index 412fa8302af..4f6313716da 100644 --- a/encodings/fsst/public-api.lock +++ b/encodings/fsst/public-api.lock @@ -72,7 +72,7 @@ pub fn vortex_fsst::FSST::compare(lhs: vortex_array::array::view::ArrayView<'_, impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_fsst::FSST -pub fn vortex_fsst::FSST::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_fsst::FSST::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::like::kernel::LikeKernel for vortex_fsst::FSST diff --git a/encodings/fsst/src/compute/cast.rs b/encodings/fsst/src/compute/cast.rs index 9553cb4d8a9..fbe3baf2a59 100644 --- a/encodings/fsst/src/compute/cast.rs +++ b/encodings/fsst/src/compute/cast.rs @@ -7,21 +7,26 @@ use vortex_array::IntoArray; use vortex_array::arrays::VarBin; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use crate::FSST; use crate::FSSTArrayExt; impl CastReduce for FSST { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // FSST is a string compression encoding. // For nullability changes, we can cast the codes and symbols arrays if array.dtype().eq_ignore_nullability(dtype) { // Cast codes array to handle nullability - let new_codes = array - .codes() - .into_array() - .cast(array.codes_dtype().with_nullability(dtype.nullability()))?; + let new_codes = array.codes().into_array().cast_opts( + array.codes_dtype().with_nullability(dtype.nullability()), + *options, + )?; Ok(Some( FSST::try_new( diff --git a/encodings/pco/public-api.lock b/encodings/pco/public-api.lock index 27fe03ed57b..9a912526d59 100644 --- a/encodings/pco/public-api.lock +++ b/encodings/pco/public-api.lock @@ -56,7 +56,7 @@ pub fn vortex_pco::Pco::slice(array: vortex_array::array::view::ArrayView<'_, Se impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_pco::Pco -pub fn vortex_pco::Pco::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_pco::Pco::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> pub struct vortex_pco::PcoChunkInfo diff --git a/encodings/pco/src/compute/cast.rs b/encodings/pco/src/compute/cast.rs index 1d5d61861a6..8db9411ad63 100644 --- a/encodings/pco/src/compute/cast.rs +++ b/encodings/pco/src/compute/cast.rs @@ -7,6 +7,7 @@ use vortex_array::IntoArray; use vortex_array::LEGACY_SESSION; use vortex_array::VortexSessionExecute; use vortex_array::dtype::DType; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_array::vtable::child_to_validity; use vortex_error::VortexResult; @@ -14,7 +15,11 @@ use vortex_error::VortexResult; use crate::Pco; use crate::PcoData; impl CastReduce for Pco { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + _options: &CastOptions, + ) -> VortexResult> { if !dtype.is_nullable() || !array .array() diff --git a/encodings/runend/public-api.lock b/encodings/runend/public-api.lock index 80d22cb75dc..f1122d4e353 100644 --- a/encodings/runend/public-api.lock +++ b/encodings/runend/public-api.lock @@ -90,7 +90,7 @@ pub fn vortex_runend::RunEnd::compare(lhs: vortex_array::array::view::ArrayView< impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_runend::RunEnd -pub fn vortex_runend::RunEnd::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_runend::RunEnd::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::kernel::FillNullReduce for vortex_runend::RunEnd diff --git a/encodings/runend/src/compute/cast.rs b/encodings/runend/src/compute/cast.rs index 4e134195d0e..bd432f4a296 100644 --- a/encodings/runend/src/compute/cast.rs +++ b/encodings/runend/src/compute/cast.rs @@ -6,15 +6,20 @@ use vortex_array::ArrayView; use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use crate::RunEnd; use crate::array::RunEndArrayExt; impl CastReduce for RunEnd { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // Cast the values array to the target type - let casted_values = array.values().cast(dtype.clone())?; + let casted_values = array.values().cast_opts(dtype.clone(), *options)?; // SAFETY: casting does not affect the ends being valid unsafe { diff --git a/encodings/sequence/public-api.lock b/encodings/sequence/public-api.lock index 455a2fd9809..5048563727c 100644 --- a/encodings/sequence/public-api.lock +++ b/encodings/sequence/public-api.lock @@ -72,7 +72,7 @@ pub fn vortex_sequence::Sequence::compare(lhs: vortex_array::array::view::ArrayV impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_sequence::Sequence -pub fn vortex_sequence::Sequence::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_sequence::Sequence::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::list_contains::kernel::ListContainsElementReduce for vortex_sequence::Sequence diff --git a/encodings/sequence/src/compute/cast.rs b/encodings/sequence/src/compute/cast.rs index b53e7188c52..a380d002d8f 100644 --- a/encodings/sequence/src/compute/cast.rs +++ b/encodings/sequence/src/compute/cast.rs @@ -8,13 +8,18 @@ use vortex_array::dtype::DType; use vortex_array::dtype::Nullability; use vortex_array::scalar::Scalar; use vortex_array::scalar::ScalarValue; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use vortex_error::vortex_err; use crate::Sequence; impl CastReduce for Sequence { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + _options: &CastOptions, + ) -> VortexResult> { // SequenceArray represents arithmetic sequences (base + i * multiplier) which // only makes sense for integer types. Floating-point sequences would accumulate // rounding errors, and other types don't support arithmetic operations. diff --git a/encodings/sparse/public-api.lock b/encodings/sparse/public-api.lock index 9bcfb086753..9fd2de7e6d7 100644 --- a/encodings/sparse/public-api.lock +++ b/encodings/sparse/public-api.lock @@ -70,7 +70,7 @@ pub fn vortex_sparse::Sparse::slice(array: vortex_array::array::view::ArrayView< impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_sparse::Sparse -pub fn vortex_sparse::Sparse::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_sparse::Sparse::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::not::kernel::NotReduce for vortex_sparse::Sparse diff --git a/encodings/sparse/src/compute/cast.rs b/encodings/sparse/src/compute/cast.rs index 4eccd273090..3d937550feb 100644 --- a/encodings/sparse/src/compute/cast.rs +++ b/encodings/sparse/src/compute/cast.rs @@ -7,16 +7,21 @@ use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; use vortex_array::scalar::Scalar; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use crate::Sparse; impl CastReduce for Sparse { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { let casted_patches = array .patches() .clone() - .map_values(|values| values.cast(dtype.clone()))?; + .map_values(|values| values.cast_opts(dtype.clone(), *options))?; let casted_fill = if array.patches().num_patches() == array.len() { // When every position is patched the fill scalar is unused and can be undefined. diff --git a/encodings/zigzag/public-api.lock b/encodings/zigzag/public-api.lock index cb514c089a8..7c089282a88 100644 --- a/encodings/zigzag/public-api.lock +++ b/encodings/zigzag/public-api.lock @@ -66,7 +66,7 @@ pub fn vortex_zigzag::ZigZag::slice(array: vortex_array::array::view::ArrayView< impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_zigzag::ZigZag -pub fn vortex_zigzag::ZigZag::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_zigzag::ZigZag::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::kernel::MaskReduce for vortex_zigzag::ZigZag diff --git a/encodings/zigzag/src/compute/cast.rs b/encodings/zigzag/src/compute/cast.rs index a71eee7a838..cb7e52c4a33 100644 --- a/encodings/zigzag/src/compute/cast.rs +++ b/encodings/zigzag/src/compute/cast.rs @@ -6,20 +6,25 @@ use vortex_array::ArrayView; use vortex_array::IntoArray; use vortex_array::builtins::ArrayBuiltins; use vortex_array::dtype::DType; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_error::VortexResult; use crate::ZigZag; use crate::array::ZigZagArrayExt; impl CastReduce for ZigZag { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { if !dtype.is_signed_int() { return Ok(None); } let new_encoded_dtype = DType::Primitive(dtype.as_ptype().to_unsigned(), dtype.nullability()); - let new_encoded = array.encoded().cast(new_encoded_dtype)?; + let new_encoded = array.encoded().cast_opts(new_encoded_dtype, *options)?; Ok(Some(ZigZag::try_new(new_encoded)?.into_array())) } } diff --git a/encodings/zstd/public-api.lock b/encodings/zstd/public-api.lock index 466229e9776..871e9606409 100644 --- a/encodings/zstd/public-api.lock +++ b/encodings/zstd/public-api.lock @@ -64,7 +64,7 @@ pub fn vortex_zstd::Zstd::slice(array: vortex_array::array::view::ArrayView<'_, impl vortex_array::scalar_fn::fns::cast::kernel::CastReduce for vortex_zstd::Zstd -pub fn vortex_zstd::Zstd::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_zstd::Zstd::cast(array: vortex_array::array::view::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> pub struct vortex_zstd::ZstdBuffersMetadata diff --git a/encodings/zstd/src/compute/cast.rs b/encodings/zstd/src/compute/cast.rs index 508fcd6231d..6e0fe32e630 100644 --- a/encodings/zstd/src/compute/cast.rs +++ b/encodings/zstd/src/compute/cast.rs @@ -6,6 +6,7 @@ use vortex_array::ArrayView; use vortex_array::IntoArray; use vortex_array::dtype::DType; use vortex_array::dtype::Nullability; +use vortex_array::scalar_fn::fns::cast::CastOptions; use vortex_array::scalar_fn::fns::cast::CastReduce; use vortex_array::validity::Validity; use vortex_array::vtable::child_to_validity; @@ -14,7 +15,11 @@ use vortex_error::VortexResult; use crate::Zstd; use crate::ZstdData; impl CastReduce for Zstd { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + _options: &CastOptions, + ) -> VortexResult> { if !dtype.eq_ignore_nullability(array.dtype()) { // Type changes can't be handled in ZSTD, need to decode and tweak. // TODO(aduffy): handle trivial conversions like Binary -> UTF8, integer widening, etc. diff --git a/vortex-array/public-api.lock b/vortex-array/public-api.lock index 8ae349c3da5..23dd1cda448 100644 --- a/vortex-array/public-api.lock +++ b/vortex-array/public-api.lock @@ -1204,7 +1204,7 @@ pub fn vortex_array::arrays::bool::BoolMaskedValidityRule::reduce_parent(&self, impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Bool -pub fn vortex_array::arrays::Bool::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Bool>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Bool::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Bool>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullKernel for vortex_array::arrays::Bool @@ -1368,7 +1368,7 @@ pub fn vortex_array::arrays::Chunked::slice(array: vortex_array::ArrayView<'_, S impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Chunked -pub fn vortex_array::arrays::Chunked::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Chunked>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Chunked::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Chunked>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullReduce for vortex_array::arrays::Chunked @@ -1536,7 +1536,7 @@ pub fn vortex_array::arrays::Constant::between(array: vortex_array::ArrayView<'_ impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Constant -pub fn vortex_array::arrays::Constant::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Constant>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Constant::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Constant>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullReduce for vortex_array::arrays::Constant @@ -1718,7 +1718,7 @@ pub fn vortex_array::arrays::Decimal::between(arr: vortex_array::ArrayView<'_, v impl vortex_array::scalar_fn::fns::cast::CastKernel for vortex_array::arrays::Decimal -pub fn vortex_array::arrays::Decimal::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Decimal>, dtype: &vortex_array::dtype::DType, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Decimal::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Decimal>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullKernel for vortex_array::arrays::Decimal @@ -1932,7 +1932,7 @@ pub fn vortex_array::arrays::dict::Dict::compare(lhs: vortex_array::ArrayView<'_ impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::dict::Dict -pub fn vortex_array::arrays::dict::Dict::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::dict::Dict>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::dict::Dict::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::dict::Dict>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullKernel for vortex_array::arrays::dict::Dict @@ -2024,7 +2024,7 @@ pub fn vortex_array::arrays::dict::Dict::compare(lhs: vortex_array::ArrayView<'_ impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::dict::Dict -pub fn vortex_array::arrays::dict::Dict::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::dict::Dict>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::dict::Dict::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::dict::Dict>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullKernel for vortex_array::arrays::dict::Dict @@ -2362,7 +2362,7 @@ pub fn vortex_array::arrays::Extension::compare(lhs: vortex_array::ArrayView<'_, impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Extension -pub fn vortex_array::arrays::Extension::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Extension>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Extension::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Extension>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::Extension @@ -2668,7 +2668,7 @@ pub fn vortex_array::arrays::FixedSizeList::slice(array: vortex_array::ArrayView impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::FixedSizeList -pub fn vortex_array::arrays::FixedSizeList::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::FixedSizeList>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::FixedSizeList::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::FixedSizeList>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::FixedSizeList @@ -2812,7 +2812,7 @@ pub fn vortex_array::arrays::List::slice(array: vortex_array::ArrayView<'_, Self impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::List -pub fn vortex_array::arrays::List::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::List>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::List::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::List>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::List @@ -2988,7 +2988,7 @@ pub fn vortex_array::arrays::ListView::slice(array: vortex_array::ArrayView<'_, impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::ListView -pub fn vortex_array::arrays::ListView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::ListView>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::ListView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::ListView>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::ListView @@ -3290,7 +3290,7 @@ pub fn vortex_array::arrays::null::Null::slice(_array: vortex_array::ArrayView<' impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::null::Null -pub fn vortex_array::arrays::null::Null::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::null::Null>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::null::Null::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::null::Null>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::null::Null @@ -3668,7 +3668,7 @@ pub fn vortex_array::arrays::Primitive::between(arr: vortex_array::ArrayView<'_, impl vortex_array::scalar_fn::fns::cast::CastKernel for vortex_array::arrays::Primitive -pub fn vortex_array::arrays::Primitive::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Primitive>, dtype: &vortex_array::dtype::DType, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Primitive::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Primitive>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullKernel for vortex_array::arrays::Primitive @@ -4396,7 +4396,7 @@ pub fn vortex_array::arrays::Struct::slice(array: vortex_array::ArrayView<'_, Se impl vortex_array::scalar_fn::fns::cast::CastKernel for vortex_array::arrays::Struct -pub fn vortex_array::arrays::Struct::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Struct>, dtype: &vortex_array::dtype::DType, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Struct::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Struct>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::Struct @@ -4564,7 +4564,7 @@ pub fn vortex_array::arrays::VarBin::compare(lhs: vortex_array::ArrayView<'_, vo impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::VarBin -pub fn vortex_array::arrays::VarBin::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBin>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::VarBin::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBin>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::VarBin @@ -4918,7 +4918,7 @@ pub fn vortex_array::arrays::VarBinView::slice(array: vortex_array::ArrayView<'_ impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::VarBinView -pub fn vortex_array::arrays::VarBinView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBinView>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::VarBinView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBinView>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::VarBinView @@ -5178,7 +5178,7 @@ pub fn vortex_array::arrays::bool::BoolMaskedValidityRule::reduce_parent(&self, impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Bool -pub fn vortex_array::arrays::Bool::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Bool>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Bool::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Bool>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullKernel for vortex_array::arrays::Bool @@ -5260,7 +5260,7 @@ pub fn vortex_array::arrays::Chunked::slice(array: vortex_array::ArrayView<'_, S impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Chunked -pub fn vortex_array::arrays::Chunked::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Chunked>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Chunked::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Chunked>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullReduce for vortex_array::arrays::Chunked @@ -5354,7 +5354,7 @@ pub fn vortex_array::arrays::Constant::between(array: vortex_array::ArrayView<'_ impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Constant -pub fn vortex_array::arrays::Constant::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Constant>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Constant::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Constant>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullReduce for vortex_array::arrays::Constant @@ -5442,7 +5442,7 @@ pub fn vortex_array::arrays::Decimal::between(arr: vortex_array::ArrayView<'_, v impl vortex_array::scalar_fn::fns::cast::CastKernel for vortex_array::arrays::Decimal -pub fn vortex_array::arrays::Decimal::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Decimal>, dtype: &vortex_array::dtype::DType, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Decimal::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Decimal>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullKernel for vortex_array::arrays::Decimal @@ -5528,7 +5528,7 @@ pub fn vortex_array::arrays::dict::Dict::compare(lhs: vortex_array::ArrayView<'_ impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::dict::Dict -pub fn vortex_array::arrays::dict::Dict::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::dict::Dict>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::dict::Dict::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::dict::Dict>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullKernel for vortex_array::arrays::dict::Dict @@ -5618,7 +5618,7 @@ pub fn vortex_array::arrays::Extension::compare(lhs: vortex_array::ArrayView<'_, impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Extension -pub fn vortex_array::arrays::Extension::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Extension>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Extension::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Extension>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::Extension @@ -5750,7 +5750,7 @@ pub fn vortex_array::arrays::FixedSizeList::slice(array: vortex_array::ArrayView impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::FixedSizeList -pub fn vortex_array::arrays::FixedSizeList::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::FixedSizeList>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::FixedSizeList::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::FixedSizeList>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::FixedSizeList @@ -5828,7 +5828,7 @@ pub fn vortex_array::arrays::List::slice(array: vortex_array::ArrayView<'_, Self impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::List -pub fn vortex_array::arrays::List::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::List>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::List::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::List>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::List @@ -5906,7 +5906,7 @@ pub fn vortex_array::arrays::ListView::slice(array: vortex_array::ArrayView<'_, impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::ListView -pub fn vortex_array::arrays::ListView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::ListView>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::ListView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::ListView>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::ListView @@ -6062,7 +6062,7 @@ pub fn vortex_array::arrays::null::Null::slice(_array: vortex_array::ArrayView<' impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::null::Null -pub fn vortex_array::arrays::null::Null::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::null::Null>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::null::Null::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::null::Null>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::null::Null @@ -6224,7 +6224,7 @@ pub fn vortex_array::arrays::Primitive::between(arr: vortex_array::ArrayView<'_, impl vortex_array::scalar_fn::fns::cast::CastKernel for vortex_array::arrays::Primitive -pub fn vortex_array::arrays::Primitive::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Primitive>, dtype: &vortex_array::dtype::DType, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Primitive::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Primitive>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::fill_null::FillNullKernel for vortex_array::arrays::Primitive @@ -6480,7 +6480,7 @@ pub fn vortex_array::arrays::Struct::slice(array: vortex_array::ArrayView<'_, Se impl vortex_array::scalar_fn::fns::cast::CastKernel for vortex_array::arrays::Struct -pub fn vortex_array::arrays::Struct::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Struct>, dtype: &vortex_array::dtype::DType, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Struct::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Struct>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::Struct @@ -6570,7 +6570,7 @@ pub fn vortex_array::arrays::VarBin::compare(lhs: vortex_array::ArrayView<'_, vo impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::VarBin -pub fn vortex_array::arrays::VarBin::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBin>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::VarBin::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBin>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::VarBin @@ -6644,7 +6644,7 @@ pub fn vortex_array::arrays::VarBinView::slice(array: vortex_array::ArrayView<'_ impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::VarBinView -pub fn vortex_array::arrays::VarBinView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBinView>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::VarBinView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBinView>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::mask::MaskReduce for vortex_array::arrays::VarBinView @@ -8262,6 +8262,8 @@ pub fn vortex_array::builtins::ArrayBuiltins::binary(&self, rhs: vortex_array::A pub fn vortex_array::builtins::ArrayBuiltins::cast(&self, dtype: vortex_array::dtype::DType) -> vortex_error::VortexResult +pub fn vortex_array::builtins::ArrayBuiltins::cast_opts(&self, dtype: vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult + pub fn vortex_array::builtins::ArrayBuiltins::fill_null(&self, fill_value: impl core::convert::Into) -> vortex_error::VortexResult pub fn vortex_array::builtins::ArrayBuiltins::get_item(&self, field_name: impl core::convert::Into) -> vortex_error::VortexResult @@ -8286,6 +8288,8 @@ pub fn vortex_array::ArrayRef::binary(&self, rhs: vortex_array::ArrayRef, op: vo pub fn vortex_array::ArrayRef::cast(&self, dtype: vortex_array::dtype::DType) -> vortex_error::VortexResult +pub fn vortex_array::ArrayRef::cast_opts(&self, dtype: vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult + pub fn vortex_array::ArrayRef::fill_null(&self, fill_value: impl core::convert::Into) -> vortex_error::VortexResult pub fn vortex_array::ArrayRef::get_item(&self, field_name: impl core::convert::Into) -> vortex_error::VortexResult @@ -8308,6 +8312,8 @@ pub fn vortex_array::builtins::ExprBuiltins::binary(&self, rhs: vortex_array::ex pub fn vortex_array::builtins::ExprBuiltins::cast(&self, dtype: vortex_array::dtype::DType) -> vortex_error::VortexResult +pub fn vortex_array::builtins::ExprBuiltins::cast_opts(&self, dtype: vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult + pub fn vortex_array::builtins::ExprBuiltins::fill_null(&self, fill_value: vortex_array::expr::Expression) -> vortex_error::VortexResult pub fn vortex_array::builtins::ExprBuiltins::get_item(&self, field_name: impl core::convert::Into) -> vortex_error::VortexResult @@ -8330,6 +8336,8 @@ pub fn vortex_array::expr::Expression::binary(&self, rhs: vortex_array::expr::Ex pub fn vortex_array::expr::Expression::cast(&self, dtype: vortex_array::dtype::DType) -> vortex_error::VortexResult +pub fn vortex_array::expr::Expression::cast_opts(&self, dtype: vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult + pub fn vortex_array::expr::Expression::fill_null(&self, fill_value: vortex_array::expr::Expression) -> vortex_error::VortexResult pub fn vortex_array::expr::Expression::get_item(&self, field_name: impl core::convert::Into) -> vortex_error::VortexResult @@ -12256,6 +12264,8 @@ pub fn vortex_array::expr::Expression::binary(&self, rhs: vortex_array::expr::Ex pub fn vortex_array::expr::Expression::cast(&self, dtype: vortex_array::dtype::DType) -> vortex_error::VortexResult +pub fn vortex_array::expr::Expression::cast_opts(&self, dtype: vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult + pub fn vortex_array::expr::Expression::fill_null(&self, fill_value: vortex_array::expr::Expression) -> vortex_error::VortexResult pub fn vortex_array::expr::Expression::get_item(&self, field_name: impl core::convert::Into) -> vortex_error::VortexResult @@ -12332,6 +12342,8 @@ pub fn vortex_array::expr::case_when_no_else(condition: vortex_array::expr::Expr pub fn vortex_array::expr::cast(child: vortex_array::expr::Expression, target: vortex_array::dtype::DType) -> vortex_array::expr::Expression +pub fn vortex_array::expr::cast_opts(child: vortex_array::expr::Expression, target: vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_array::expr::Expression + pub fn vortex_array::expr::checked_add(lhs: vortex_array::expr::Expression, rhs: vortex_array::expr::Expression) -> vortex_array::expr::Expression pub fn vortex_array::expr::col(field: impl core::convert::Into) -> vortex_array::expr::Expression @@ -14688,6 +14700,8 @@ impl vortex_array::scalar::Scalar pub fn vortex_array::scalar::Scalar::cast(&self, target_dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult +pub fn vortex_array::scalar::Scalar::cast_opts(&self, target_dtype: &vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult + pub fn vortex_array::scalar::Scalar::into_nullable(self) -> vortex_array::scalar::Scalar impl vortex_array::scalar::Scalar @@ -15242,6 +15256,8 @@ impl<'a> vortex_array::scalar::StructScalar<'a> pub fn vortex_array::scalar::StructScalar<'a>::cast(&self, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult +pub fn vortex_array::scalar::StructScalar<'a>::cast_opts(&self, dtype: &vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult + pub fn vortex_array::scalar::StructScalar<'a>::dtype(&self) -> &'a vortex_array::dtype::DType pub fn vortex_array::scalar::StructScalar<'a>::field(&self, name: impl core::convert::AsRef) -> core::option::Option @@ -15762,6 +15778,46 @@ impl core::marker::StructuralPartialEq for vortex_array::scalar_fn::fns::case_wh pub mod vortex_array::scalar_fn::fns::cast +pub enum vortex_array::scalar_fn::fns::cast::CastMode + +pub vortex_array::scalar_fn::fns::cast::CastMode::ByName + +pub vortex_array::scalar_fn::fns::cast::CastMode::ByPosition + +impl vortex_array::scalar_fn::fns::cast::CastMode + +pub fn vortex_array::scalar_fn::fns::cast::CastMode::name(&self) -> &'static str + +impl core::clone::Clone for vortex_array::scalar_fn::fns::cast::CastMode + +pub fn vortex_array::scalar_fn::fns::cast::CastMode::clone(&self) -> vortex_array::scalar_fn::fns::cast::CastMode + +impl core::cmp::Eq for vortex_array::scalar_fn::fns::cast::CastMode + +impl core::cmp::PartialEq for vortex_array::scalar_fn::fns::cast::CastMode + +pub fn vortex_array::scalar_fn::fns::cast::CastMode::eq(&self, other: &vortex_array::scalar_fn::fns::cast::CastMode) -> bool + +impl core::convert::From for vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::from(mode: vortex_array::scalar_fn::fns::cast::CastMode) -> Self + +impl core::convert::From for vortex_array::scalar_fn::fns::cast::CastMode + +pub fn vortex_array::scalar_fn::fns::cast::CastMode::from(mode: vortex_proto::expr::CastMode) -> Self + +impl core::fmt::Debug for vortex_array::scalar_fn::fns::cast::CastMode + +pub fn vortex_array::scalar_fn::fns::cast::CastMode::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::hash::Hash for vortex_array::scalar_fn::fns::cast::CastMode + +pub fn vortex_array::scalar_fn::fns::cast::CastMode::hash<__H: core::hash::Hasher>(&self, state: &mut __H) + +impl core::marker::Copy for vortex_array::scalar_fn::fns::cast::CastMode + +impl core::marker::StructuralPartialEq for vortex_array::scalar_fn::fns::cast::CastMode + pub struct vortex_array::scalar_fn::fns::cast::Cast impl core::clone::Clone for vortex_array::scalar_fn::fns::cast::Cast @@ -15770,41 +15826,41 @@ pub fn vortex_array::scalar_fn::fns::cast::Cast::clone(&self) -> vortex_array::s impl vortex_array::scalar_fn::ScalarFnVTable for vortex_array::scalar_fn::fns::cast::Cast -pub type vortex_array::scalar_fn::fns::cast::Cast::Options = vortex_array::dtype::DType +pub type vortex_array::scalar_fn::fns::cast::Cast::Options = vortex_array::scalar_fn::fns::cast::CastFnOptions -pub fn vortex_array::scalar_fn::fns::cast::Cast::arity(&self, _options: &vortex_array::dtype::DType) -> vortex_array::scalar_fn::Arity +pub fn vortex_array::scalar_fn::fns::cast::Cast::arity(&self, _options: &vortex_array::scalar_fn::fns::cast::CastFnOptions) -> vortex_array::scalar_fn::Arity -pub fn vortex_array::scalar_fn::fns::cast::Cast::child_name(&self, _instance: &vortex_array::dtype::DType, child_idx: usize) -> vortex_array::scalar_fn::ChildName +pub fn vortex_array::scalar_fn::fns::cast::Cast::child_name(&self, _instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, child_idx: usize) -> vortex_array::scalar_fn::ChildName pub fn vortex_array::scalar_fn::fns::cast::Cast::coerce_args(&self, options: &Self::Options, args: &[vortex_array::dtype::DType]) -> vortex_error::VortexResult> pub fn vortex_array::scalar_fn::fns::cast::Cast::deserialize(&self, _metadata: &[u8], session: &vortex_session::VortexSession) -> vortex_error::VortexResult -pub fn vortex_array::scalar_fn::fns::cast::Cast::execute(&self, target_dtype: &vortex_array::dtype::DType, args: &dyn vortex_array::scalar_fn::ExecutionArgs, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult +pub fn vortex_array::scalar_fn::fns::cast::Cast::execute(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, args: &dyn vortex_array::scalar_fn::ExecutionArgs, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult -pub fn vortex_array::scalar_fn::fns::cast::Cast::fmt_sql(&self, dtype: &vortex_array::dtype::DType, expr: &vortex_array::expr::Expression, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn vortex_array::scalar_fn::fns::cast::Cast::fmt_sql(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, expr: &vortex_array::expr::Expression, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result pub fn vortex_array::scalar_fn::fns::cast::Cast::id(&self) -> vortex_array::scalar_fn::ScalarFnId pub fn vortex_array::scalar_fn::fns::cast::Cast::is_fallible(&self, options: &Self::Options) -> bool -pub fn vortex_array::scalar_fn::fns::cast::Cast::is_null_sensitive(&self, _instance: &vortex_array::dtype::DType) -> bool +pub fn vortex_array::scalar_fn::fns::cast::Cast::is_null_sensitive(&self, _instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions) -> bool -pub fn vortex_array::scalar_fn::fns::cast::Cast::reduce(&self, target_dtype: &vortex_array::dtype::DType, node: &dyn vortex_array::scalar_fn::ReduceNode, _ctx: &dyn vortex_array::scalar_fn::ReduceCtx) -> vortex_error::VortexResult> +pub fn vortex_array::scalar_fn::fns::cast::Cast::reduce(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, node: &dyn vortex_array::scalar_fn::ReduceNode, _ctx: &dyn vortex_array::scalar_fn::ReduceCtx) -> vortex_error::VortexResult> -pub fn vortex_array::scalar_fn::fns::cast::Cast::return_dtype(&self, dtype: &vortex_array::dtype::DType, _arg_dtypes: &[vortex_array::dtype::DType]) -> vortex_error::VortexResult +pub fn vortex_array::scalar_fn::fns::cast::Cast::return_dtype(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, _arg_dtypes: &[vortex_array::dtype::DType]) -> vortex_error::VortexResult -pub fn vortex_array::scalar_fn::fns::cast::Cast::serialize(&self, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult>> +pub fn vortex_array::scalar_fn::fns::cast::Cast::serialize(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions) -> vortex_error::VortexResult>> pub fn vortex_array::scalar_fn::fns::cast::Cast::simplify(&self, options: &Self::Options, expr: &vortex_array::expr::Expression, ctx: &dyn vortex_array::scalar_fn::SimplifyCtx) -> vortex_error::VortexResult> pub fn vortex_array::scalar_fn::fns::cast::Cast::simplify_untyped(&self, options: &Self::Options, expr: &vortex_array::expr::Expression) -> vortex_error::VortexResult> -pub fn vortex_array::scalar_fn::fns::cast::Cast::stat_expression(&self, dtype: &vortex_array::dtype::DType, expr: &vortex_array::expr::Expression, stat: vortex_array::expr::stats::Stat, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option +pub fn vortex_array::scalar_fn::fns::cast::Cast::stat_expression(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, expr: &vortex_array::expr::Expression, stat: vortex_array::expr::stats::Stat, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option pub fn vortex_array::scalar_fn::fns::cast::Cast::stat_falsification(&self, options: &Self::Options, expr: &vortex_array::expr::Expression, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option -pub fn vortex_array::scalar_fn::fns::cast::Cast::validity(&self, dtype: &vortex_array::dtype::DType, expression: &vortex_array::expr::Expression) -> vortex_error::VortexResult> +pub fn vortex_array::scalar_fn::fns::cast::Cast::validity(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, expression: &vortex_array::expr::Expression) -> vortex_error::VortexResult> pub struct vortex_array::scalar_fn::fns::cast::CastExecuteAdaptor(pub V) @@ -15822,6 +15878,78 @@ pub type vortex_array::scalar_fn::fns::cast::CastExecuteAdaptor::Parent = vor pub fn vortex_array::scalar_fn::fns::cast::CastExecuteAdaptor::execute_parent(&self, array: vortex_array::ArrayView<'_, V>, parent: ::Match, _child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub struct vortex_array::scalar_fn::fns::cast::CastFnOptions + +impl vortex_array::scalar_fn::fns::cast::CastFnOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastFnOptions::new(target: vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> Self + +pub fn vortex_array::scalar_fn::fns::cast::CastFnOptions::options(&self) -> &vortex_array::scalar_fn::fns::cast::CastOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastFnOptions::target(&self) -> &vortex_array::dtype::DType + +impl core::clone::Clone for vortex_array::scalar_fn::fns::cast::CastFnOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastFnOptions::clone(&self) -> vortex_array::scalar_fn::fns::cast::CastFnOptions + +impl core::cmp::Eq for vortex_array::scalar_fn::fns::cast::CastFnOptions + +impl core::cmp::PartialEq for vortex_array::scalar_fn::fns::cast::CastFnOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastFnOptions::eq(&self, other: &vortex_array::scalar_fn::fns::cast::CastFnOptions) -> bool + +impl core::fmt::Debug for vortex_array::scalar_fn::fns::cast::CastFnOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastFnOptions::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::fmt::Display for vortex_array::scalar_fn::fns::cast::CastFnOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastFnOptions::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::hash::Hash for vortex_array::scalar_fn::fns::cast::CastFnOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastFnOptions::hash<__H: core::hash::Hasher>(&self, state: &mut __H) + +impl core::marker::StructuralPartialEq for vortex_array::scalar_fn::fns::cast::CastFnOptions + +pub struct vortex_array::scalar_fn::fns::cast::CastOptions + +impl vortex_array::scalar_fn::fns::cast::CastOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastOptions::by_name() -> Self + +pub fn vortex_array::scalar_fn::fns::cast::CastOptions::by_position() -> Self + +pub fn vortex_array::scalar_fn::fns::cast::CastOptions::mode(&self) -> vortex_array::scalar_fn::fns::cast::CastMode + +pub fn vortex_array::scalar_fn::fns::cast::CastOptions::new(mode: vortex_array::scalar_fn::fns::cast::CastMode) -> Self + +impl core::clone::Clone for vortex_array::scalar_fn::fns::cast::CastOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastOptions::clone(&self) -> vortex_array::scalar_fn::fns::cast::CastOptions + +impl core::cmp::Eq for vortex_array::scalar_fn::fns::cast::CastOptions + +impl core::cmp::PartialEq for vortex_array::scalar_fn::fns::cast::CastOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastOptions::eq(&self, other: &vortex_array::scalar_fn::fns::cast::CastOptions) -> bool + +impl core::fmt::Debug for vortex_array::scalar_fn::fns::cast::CastOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastOptions::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::fmt::Display for vortex_array::scalar_fn::fns::cast::CastOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastOptions::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::hash::Hash for vortex_array::scalar_fn::fns::cast::CastOptions + +pub fn vortex_array::scalar_fn::fns::cast::CastOptions::hash<__H: core::hash::Hasher>(&self, state: &mut __H) + +impl core::marker::Copy for vortex_array::scalar_fn::fns::cast::CastOptions + +impl core::marker::StructuralPartialEq for vortex_array::scalar_fn::fns::cast::CastOptions + pub struct vortex_array::scalar_fn::fns::cast::CastReduceAdaptor(pub V) impl core::default::Default for vortex_array::scalar_fn::fns::cast::CastReduceAdaptor @@ -15840,67 +15968,67 @@ pub fn vortex_array::scalar_fn::fns::cast::CastReduceAdaptor::reduce_parent(& pub trait vortex_array::scalar_fn::fns::cast::CastKernel: vortex_array::VTable -pub fn vortex_array::scalar_fn::fns::cast::CastKernel::cast(array: vortex_array::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::scalar_fn::fns::cast::CastKernel::cast(array: vortex_array::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastKernel for vortex_array::arrays::Decimal -pub fn vortex_array::arrays::Decimal::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Decimal>, dtype: &vortex_array::dtype::DType, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Decimal::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Decimal>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastKernel for vortex_array::arrays::Primitive -pub fn vortex_array::arrays::Primitive::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Primitive>, dtype: &vortex_array::dtype::DType, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Primitive::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Primitive>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastKernel for vortex_array::arrays::Struct -pub fn vortex_array::arrays::Struct::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Struct>, dtype: &vortex_array::dtype::DType, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Struct::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Struct>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> pub trait vortex_array::scalar_fn::fns::cast::CastReduce: vortex_array::VTable -pub fn vortex_array::scalar_fn::fns::cast::CastReduce::cast(array: vortex_array::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::scalar_fn::fns::cast::CastReduce::cast(array: vortex_array::ArrayView<'_, Self>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Bool -pub fn vortex_array::arrays::Bool::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Bool>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Bool::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Bool>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Chunked -pub fn vortex_array::arrays::Chunked::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Chunked>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Chunked::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Chunked>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Constant -pub fn vortex_array::arrays::Constant::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Constant>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Constant::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Constant>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::Extension -pub fn vortex_array::arrays::Extension::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Extension>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::Extension::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::Extension>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::FixedSizeList -pub fn vortex_array::arrays::FixedSizeList::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::FixedSizeList>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::FixedSizeList::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::FixedSizeList>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::List -pub fn vortex_array::arrays::List::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::List>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::List::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::List>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::ListView -pub fn vortex_array::arrays::ListView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::ListView>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::ListView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::ListView>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::VarBin -pub fn vortex_array::arrays::VarBin::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBin>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::VarBin::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBin>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::VarBinView -pub fn vortex_array::arrays::VarBinView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBinView>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::VarBinView::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::VarBinView>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::dict::Dict -pub fn vortex_array::arrays::dict::Dict::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::dict::Dict>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::dict::Dict::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::dict::Dict>, dtype: &vortex_array::dtype::DType, options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::fns::cast::CastReduce for vortex_array::arrays::null::Null -pub fn vortex_array::arrays::null::Null::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::null::Null>, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult> +pub fn vortex_array::arrays::null::Null::cast(array: vortex_array::ArrayView<'_, vortex_array::arrays::null::Null>, dtype: &vortex_array::dtype::DType, _options: &vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult> pub mod vortex_array::scalar_fn::fns::dynamic @@ -17818,41 +17946,41 @@ pub fn vortex_array::scalar_fn::fns::case_when::CaseWhen::validity(&self, option impl vortex_array::scalar_fn::ScalarFnVTable for vortex_array::scalar_fn::fns::cast::Cast -pub type vortex_array::scalar_fn::fns::cast::Cast::Options = vortex_array::dtype::DType +pub type vortex_array::scalar_fn::fns::cast::Cast::Options = vortex_array::scalar_fn::fns::cast::CastFnOptions -pub fn vortex_array::scalar_fn::fns::cast::Cast::arity(&self, _options: &vortex_array::dtype::DType) -> vortex_array::scalar_fn::Arity +pub fn vortex_array::scalar_fn::fns::cast::Cast::arity(&self, _options: &vortex_array::scalar_fn::fns::cast::CastFnOptions) -> vortex_array::scalar_fn::Arity -pub fn vortex_array::scalar_fn::fns::cast::Cast::child_name(&self, _instance: &vortex_array::dtype::DType, child_idx: usize) -> vortex_array::scalar_fn::ChildName +pub fn vortex_array::scalar_fn::fns::cast::Cast::child_name(&self, _instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, child_idx: usize) -> vortex_array::scalar_fn::ChildName pub fn vortex_array::scalar_fn::fns::cast::Cast::coerce_args(&self, options: &Self::Options, args: &[vortex_array::dtype::DType]) -> vortex_error::VortexResult> pub fn vortex_array::scalar_fn::fns::cast::Cast::deserialize(&self, _metadata: &[u8], session: &vortex_session::VortexSession) -> vortex_error::VortexResult -pub fn vortex_array::scalar_fn::fns::cast::Cast::execute(&self, target_dtype: &vortex_array::dtype::DType, args: &dyn vortex_array::scalar_fn::ExecutionArgs, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult +pub fn vortex_array::scalar_fn::fns::cast::Cast::execute(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, args: &dyn vortex_array::scalar_fn::ExecutionArgs, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult -pub fn vortex_array::scalar_fn::fns::cast::Cast::fmt_sql(&self, dtype: &vortex_array::dtype::DType, expr: &vortex_array::expr::Expression, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn vortex_array::scalar_fn::fns::cast::Cast::fmt_sql(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, expr: &vortex_array::expr::Expression, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result pub fn vortex_array::scalar_fn::fns::cast::Cast::id(&self) -> vortex_array::scalar_fn::ScalarFnId pub fn vortex_array::scalar_fn::fns::cast::Cast::is_fallible(&self, options: &Self::Options) -> bool -pub fn vortex_array::scalar_fn::fns::cast::Cast::is_null_sensitive(&self, _instance: &vortex_array::dtype::DType) -> bool +pub fn vortex_array::scalar_fn::fns::cast::Cast::is_null_sensitive(&self, _instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions) -> bool -pub fn vortex_array::scalar_fn::fns::cast::Cast::reduce(&self, target_dtype: &vortex_array::dtype::DType, node: &dyn vortex_array::scalar_fn::ReduceNode, _ctx: &dyn vortex_array::scalar_fn::ReduceCtx) -> vortex_error::VortexResult> +pub fn vortex_array::scalar_fn::fns::cast::Cast::reduce(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, node: &dyn vortex_array::scalar_fn::ReduceNode, _ctx: &dyn vortex_array::scalar_fn::ReduceCtx) -> vortex_error::VortexResult> -pub fn vortex_array::scalar_fn::fns::cast::Cast::return_dtype(&self, dtype: &vortex_array::dtype::DType, _arg_dtypes: &[vortex_array::dtype::DType]) -> vortex_error::VortexResult +pub fn vortex_array::scalar_fn::fns::cast::Cast::return_dtype(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, _arg_dtypes: &[vortex_array::dtype::DType]) -> vortex_error::VortexResult -pub fn vortex_array::scalar_fn::fns::cast::Cast::serialize(&self, dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult>> +pub fn vortex_array::scalar_fn::fns::cast::Cast::serialize(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions) -> vortex_error::VortexResult>> pub fn vortex_array::scalar_fn::fns::cast::Cast::simplify(&self, options: &Self::Options, expr: &vortex_array::expr::Expression, ctx: &dyn vortex_array::scalar_fn::SimplifyCtx) -> vortex_error::VortexResult> pub fn vortex_array::scalar_fn::fns::cast::Cast::simplify_untyped(&self, options: &Self::Options, expr: &vortex_array::expr::Expression) -> vortex_error::VortexResult> -pub fn vortex_array::scalar_fn::fns::cast::Cast::stat_expression(&self, dtype: &vortex_array::dtype::DType, expr: &vortex_array::expr::Expression, stat: vortex_array::expr::stats::Stat, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option +pub fn vortex_array::scalar_fn::fns::cast::Cast::stat_expression(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, expr: &vortex_array::expr::Expression, stat: vortex_array::expr::stats::Stat, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option pub fn vortex_array::scalar_fn::fns::cast::Cast::stat_falsification(&self, options: &Self::Options, expr: &vortex_array::expr::Expression, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option -pub fn vortex_array::scalar_fn::fns::cast::Cast::validity(&self, dtype: &vortex_array::dtype::DType, expression: &vortex_array::expr::Expression) -> vortex_error::VortexResult> +pub fn vortex_array::scalar_fn::fns::cast::Cast::validity(&self, instance: &vortex_array::scalar_fn::fns::cast::CastFnOptions, expression: &vortex_array::expr::Expression) -> vortex_error::VortexResult> impl vortex_array::scalar_fn::ScalarFnVTable for vortex_array::scalar_fn::fns::dynamic::DynamicComparison @@ -22336,6 +22464,8 @@ pub fn vortex_array::ArrayRef::binary(&self, rhs: vortex_array::ArrayRef, op: vo pub fn vortex_array::ArrayRef::cast(&self, dtype: vortex_array::dtype::DType) -> vortex_error::VortexResult +pub fn vortex_array::ArrayRef::cast_opts(&self, dtype: vortex_array::dtype::DType, options: vortex_array::scalar_fn::fns::cast::CastOptions) -> vortex_error::VortexResult + pub fn vortex_array::ArrayRef::fill_null(&self, fill_value: impl core::convert::Into) -> vortex_error::VortexResult pub fn vortex_array::ArrayRef::get_item(&self, field_name: impl core::convert::Into) -> vortex_error::VortexResult diff --git a/vortex-array/src/arrays/bool/compute/cast.rs b/vortex-array/src/arrays/bool/compute/cast.rs index 3b5fbea7607..8c1e1a24709 100644 --- a/vortex-array/src/arrays/bool/compute/cast.rs +++ b/vortex-array/src/arrays/bool/compute/cast.rs @@ -10,10 +10,15 @@ use crate::arrays::Bool; use crate::arrays::BoolArray; use crate::arrays::bool::BoolArrayExt; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; impl CastReduce for Bool { - fn cast(array: ArrayView<'_, Bool>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Bool>, + dtype: &DType, + _options: &CastOptions, + ) -> VortexResult> { if !matches!(dtype, DType::Bool(_)) { return Ok(None); } diff --git a/vortex-array/src/arrays/chunked/compute/cast.rs b/vortex-array/src/arrays/chunked/compute/cast.rs index 9eed54d4300..630240d80b4 100644 --- a/vortex-array/src/arrays/chunked/compute/cast.rs +++ b/vortex-array/src/arrays/chunked/compute/cast.rs @@ -11,13 +11,18 @@ use crate::arrays::ChunkedArray; use crate::arrays::chunked::ChunkedArrayExt; use crate::builtins::ArrayBuiltins; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; impl CastReduce for Chunked { - fn cast(array: ArrayView<'_, Chunked>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Chunked>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { let mut cast_chunks = Vec::new(); for chunk in array.iter_chunks() { - cast_chunks.push(chunk.cast(dtype.clone())?); + cast_chunks.push(chunk.cast_opts(dtype.clone(), *options)?); } // SAFETY: casting all chunks retains all chunks have same DType diff --git a/vortex-array/src/arrays/constant/compute/cast.rs b/vortex-array/src/arrays/constant/compute/cast.rs index 68c6dbeb758..31183327cfa 100644 --- a/vortex-array/src/arrays/constant/compute/cast.rs +++ b/vortex-array/src/arrays/constant/compute/cast.rs @@ -9,25 +9,43 @@ use crate::array::ArrayView; use crate::arrays::Constant; use crate::arrays::ConstantArray; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; impl CastReduce for Constant { - fn cast(array: ArrayView<'_, Constant>, dtype: &DType) -> VortexResult> { - match array.scalar().cast(dtype) { - Ok(scalar) => Ok(Some(ConstantArray::new(scalar, array.len()).into_array())), - Err(_e) => Ok(None), - } + fn cast( + array: ArrayView<'_, Constant>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { + let scalar = array.scalar().cast_opts(dtype, *options)?; + Ok(Some(ConstantArray::new(scalar, array.len()).into_array())) } } #[cfg(test)] mod tests { + use std::sync::LazyLock; + use rstest::rstest; + use vortex_session::VortexSession; use crate::IntoArray; + use crate::VortexSessionExecute; use crate::arrays::ConstantArray; + use crate::arrays::StructArray; + use crate::arrays::struct_::StructArrayExt; + use crate::builtins::ArrayBuiltins; use crate::compute::conformance::cast::test_cast_conformance; + use crate::dtype::DType; + use crate::dtype::Nullability; + use crate::dtype::PType; use crate::scalar::Scalar; + use crate::scalar_fn::fns::cast::CastOptions; + use crate::session::ArraySession; + + static SESSION: LazyLock = + LazyLock::new(|| VortexSession::empty().with::()); #[rstest] #[case(ConstantArray::new(Scalar::from(42u32), 5).into_array())] @@ -39,4 +57,198 @@ mod tests { fn test_cast_constant_conformance(#[case] array: crate::ArrayRef) { test_cast_conformance(&array); } + + fn source_struct_dtype() -> DType { + DType::struct_( + [ + ("a", DType::Primitive(PType::I32, Nullability::NonNullable)), + ("b", DType::Primitive(PType::I64, Nullability::NonNullable)), + ], + Nullability::NonNullable, + ) + } + + fn source_struct_scalar() -> Scalar { + Scalar::struct_( + source_struct_dtype(), + vec![Scalar::from(1i32), Scalar::from(10i64)], + ) + } + + #[test] + fn cast_constant_struct_by_position_renames_fields() { + let source = ConstantArray::new(source_struct_scalar(), 3).into_array(); + let target = DType::struct_( + [ + ("x", DType::Primitive(PType::I32, Nullability::NonNullable)), + ("y", DType::Primitive(PType::I64, Nullability::NonNullable)), + ], + Nullability::NonNullable, + ); + + let result = source + .cast_opts(target.clone(), CastOptions::by_position()) + .unwrap(); + assert_eq!(result.dtype(), &target); + assert_eq!(result.len(), 3); + let s = result + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap(); + assert_eq!( + s.unmasked_field_by_name("x") + .unwrap() + .execute_scalar(0, &mut SESSION.create_execution_ctx()) + .unwrap(), + Scalar::from(1i32) + ); + assert_eq!( + s.unmasked_field_by_name("y") + .unwrap() + .execute_scalar(0, &mut SESSION.create_execution_ctx()) + .unwrap(), + Scalar::from(10i64) + ); + } + + #[test] + fn cast_constant_struct_by_name_schema_evolution() { + let source = ConstantArray::new(source_struct_scalar(), 2).into_array(); + let target = DType::struct_( + [ + ("a", DType::Primitive(PType::I32, Nullability::NonNullable)), + ("b", DType::Primitive(PType::I64, Nullability::NonNullable)), + ("c", DType::Primitive(PType::I32, Nullability::Nullable)), + ], + Nullability::NonNullable, + ); + + let result = source + .cast_opts(target.clone(), CastOptions::by_name()) + .unwrap(); + assert_eq!(result.dtype(), &target); + let s = result + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap(); + assert_eq!( + s.unmasked_field_by_name("a") + .unwrap() + .execute_scalar(0, &mut SESSION.create_execution_ctx()) + .unwrap(), + Scalar::from(1i32) + ); + assert_eq!( + s.unmasked_field_by_name("b") + .unwrap() + .execute_scalar(0, &mut SESSION.create_execution_ctx()) + .unwrap(), + Scalar::from(10i64) + ); + assert!( + s.unmasked_field_by_name("c") + .unwrap() + .execute_scalar(0, &mut SESSION.create_execution_ctx()) + .unwrap() + .is_null() + ); + } + + #[test] + fn cast_constant_struct_by_name_reorders_fields() { + let source = ConstantArray::new(source_struct_scalar(), 1).into_array(); + let target = DType::struct_( + [ + ("b", DType::Primitive(PType::I64, Nullability::NonNullable)), + ("a", DType::Primitive(PType::I32, Nullability::NonNullable)), + ], + Nullability::NonNullable, + ); + + let result = source + .cast_opts(target.clone(), CastOptions::by_name()) + .unwrap(); + assert_eq!(result.dtype(), &target); + let s = result + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap(); + assert_eq!( + s.unmasked_field_by_name("a") + .unwrap() + .execute_scalar(0, &mut SESSION.create_execution_ctx()) + .unwrap(), + Scalar::from(1i32) + ); + assert_eq!( + s.unmasked_field_by_name("b") + .unwrap() + .execute_scalar(0, &mut SESSION.create_execution_ctx()) + .unwrap(), + Scalar::from(10i64) + ); + } + + #[test] + fn cast_constant_struct_by_name_requires_nullable_added_field() { + let source = ConstantArray::new(source_struct_scalar(), 1).into_array(); + let target = DType::struct_( + [ + ("a", DType::Primitive(PType::I32, Nullability::NonNullable)), + ("b", DType::Primitive(PType::I64, Nullability::NonNullable)), + ("c", DType::Primitive(PType::I32, Nullability::NonNullable)), + ], + Nullability::NonNullable, + ); + + assert!( + source.cast_opts(target, CastOptions::by_name()).is_err(), + "adding non-nullable field should fail" + ); + } + + #[test] + fn cast_constant_struct_by_position_field_count_mismatch_fails() { + let source = ConstantArray::new(source_struct_scalar(), 1).into_array(); + let target = DType::struct_( + [("x", DType::Primitive(PType::I32, Nullability::NonNullable))], + Nullability::NonNullable, + ); + + assert!( + source + .cast_opts(target, CastOptions::by_position()) + .is_err() + ); + } + + #[test] + fn cast_constant_struct_by_name_duplicate_source_names_fails() { + // Shape differs from the target so the cast cannot short-circuit via + // `eq_ignore_nullability`; forces ByName resolution which must reject duplicate names. + let dup_src_dtype = DType::struct_( + [ + ("a", DType::Primitive(PType::I32, Nullability::NonNullable)), + ("a", DType::Primitive(PType::I64, Nullability::NonNullable)), + ], + Nullability::NonNullable, + ); + let source = ConstantArray::new( + Scalar::struct_(dup_src_dtype, vec![Scalar::from(1i32), Scalar::from(10i64)]), + 1, + ) + .into_array(); + + let target = DType::struct_( + [ + ("a", DType::Primitive(PType::I32, Nullability::NonNullable)), + ("b", DType::Primitive(PType::I64, Nullability::NonNullable)), + ], + Nullability::NonNullable, + ); + let err = source + .cast_opts(target, CastOptions::by_name()) + .unwrap_err(); + assert!( + err.to_string().contains("unique"), + "expected uniqueness error, got: {err}" + ); + } } diff --git a/vortex-array/src/arrays/decimal/compute/cast.rs b/vortex-array/src/arrays/decimal/compute/cast.rs index 80155954214..98eb8763faf 100644 --- a/vortex-array/src/arrays/decimal/compute/cast.rs +++ b/vortex-array/src/arrays/decimal/compute/cast.rs @@ -18,11 +18,13 @@ use crate::dtype::DecimalType; use crate::dtype::NativeDecimalType; use crate::match_each_decimal_value_type; use crate::scalar_fn::fns::cast::CastKernel; +use crate::scalar_fn::fns::cast::CastOptions; impl CastKernel for Decimal { fn cast( array: ArrayView<'_, Decimal>, dtype: &DType, + _options: &CastOptions, _ctx: &mut ExecutionCtx, ) -> VortexResult> { // Early return if not casting to decimal diff --git a/vortex-array/src/arrays/dict/compute/cast.rs b/vortex-array/src/arrays/dict/compute/cast.rs index c9575c32ae2..dcc50bc4856 100644 --- a/vortex-array/src/arrays/dict/compute/cast.rs +++ b/vortex-array/src/arrays/dict/compute/cast.rs @@ -12,11 +12,16 @@ use crate::arrays::dict::DictArrayExt; use crate::arrays::dict::DictArraySlotsExt; use crate::builtins::ArrayBuiltins; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; use crate::validity::Validity; impl CastReduce for Dict { - fn cast(array: ArrayView<'_, Dict>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Dict>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // Can have un-reference null values making the cast of values fail without a possible mask. // TODO(joe): optimize this, could look at accessible values and fill_null not those? if !dtype.is_nullable() @@ -29,13 +34,14 @@ impl CastReduce for Dict { return Ok(None); } // Cast the dictionary values to the target type - let casted_values = array.values().cast(dtype.clone())?; + let casted_values = array.values().cast_opts(dtype.clone(), *options)?; // If the codes are nullable but we are casting to non nullable dtype we have to remove nullability from codes as well let casted_codes = if array.codes().dtype().is_nullable() && !dtype.is_nullable() { - array - .codes() - .cast(array.codes().dtype().with_nullability(dtype.nullability()))? + array.codes().cast_opts( + array.codes().dtype().with_nullability(dtype.nullability()), + *options, + )? } else { array.codes().clone() }; diff --git a/vortex-array/src/arrays/extension/compute/cast.rs b/vortex-array/src/arrays/extension/compute/cast.rs index af42fd5c9ea..71779de2f82 100644 --- a/vortex-array/src/arrays/extension/compute/cast.rs +++ b/vortex-array/src/arrays/extension/compute/cast.rs @@ -9,12 +9,14 @@ use crate::arrays::ExtensionArray; use crate::arrays::extension::ExtensionArrayExt; use crate::builtins::ArrayBuiltins; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; impl CastReduce for Extension { fn cast( array: ArrayView<'_, Extension>, dtype: &DType, + options: &CastOptions, ) -> vortex_error::VortexResult> { if !array.dtype().eq_ignore_nullability(dtype) { // Target is not the same extension type. @@ -28,7 +30,7 @@ impl CastReduce for Extension { let new_storage = match array .storage_array() - .cast(ext_dtype.storage_dtype().clone()) + .cast_opts(ext_dtype.storage_dtype().clone(), *options) { Ok(arr) => arr, Err(e) => { diff --git a/vortex-array/src/arrays/fixed_size_list/compute/cast.rs b/vortex-array/src/arrays/fixed_size_list/compute/cast.rs index 791462d51c9..c21ab4e7366 100644 --- a/vortex-array/src/arrays/fixed_size_list/compute/cast.rs +++ b/vortex-array/src/arrays/fixed_size_list/compute/cast.rs @@ -11,6 +11,7 @@ use crate::arrays::FixedSizeListArray; use crate::arrays::fixed_size_list::FixedSizeListArrayExt; use crate::builtins::ArrayBuiltins; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; /// Cast implementation for [`FixedSizeListArray`]. @@ -18,12 +19,18 @@ use crate::scalar_fn::fns::cast::CastReduce; /// Recursively casts the inner elements array to the target element type while preserving the list /// structure. impl CastReduce for FixedSizeList { - fn cast(array: ArrayView<'_, FixedSizeList>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, FixedSizeList>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { let Some(target_element_type) = dtype.as_fixed_size_list_element_opt() else { return Ok(None); }; - let elements = array.elements().cast((**target_element_type).clone())?; + let elements = array + .elements() + .cast_opts((**target_element_type).clone(), *options)?; let validity = array .validity()? .cast_nullability(dtype.nullability(), array.len())?; diff --git a/vortex-array/src/arrays/list/compute/cast.rs b/vortex-array/src/arrays/list/compute/cast.rs index c9813cfe92d..1c6db03be98 100644 --- a/vortex-array/src/arrays/list/compute/cast.rs +++ b/vortex-array/src/arrays/list/compute/cast.rs @@ -11,10 +11,15 @@ use crate::arrays::ListArray; use crate::arrays::list::ListArrayExt; use crate::builtins::ArrayBuiltins; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; impl CastReduce for List { - fn cast(array: ArrayView<'_, List>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, List>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { let Some(target_element_type) = dtype.as_list_element_opt() else { return Ok(None); }; @@ -23,7 +28,9 @@ impl CastReduce for List { .validity()? .cast_nullability(dtype.nullability(), array.len())?; - let new_elements = array.elements().cast((**target_element_type).clone())?; + let new_elements = array + .elements() + .cast_opts((**target_element_type).clone(), *options)?; ListArray::try_new(new_elements, array.offsets().clone(), validity) .map(|a| Some(a.into_array())) diff --git a/vortex-array/src/arrays/listview/compute/cast.rs b/vortex-array/src/arrays/listview/compute/cast.rs index 77cd7ab7736..dcc3334c8fa 100644 --- a/vortex-array/src/arrays/listview/compute/cast.rs +++ b/vortex-array/src/arrays/listview/compute/cast.rs @@ -11,17 +11,24 @@ use crate::arrays::ListViewArray; use crate::arrays::listview::ListViewArrayExt; use crate::builtins::ArrayBuiltins; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; impl CastReduce for ListView { - fn cast(array: ArrayView<'_, ListView>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, ListView>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult> { // Check if we're casting to a `List` type. let Some(target_element_type) = dtype.as_list_element_opt() else { return Ok(None); }; // Cast the elements to the target element type. - let new_elements = array.elements().cast((**target_element_type).clone())?; + let new_elements = array + .elements() + .cast_opts((**target_element_type).clone(), *options)?; let validity = array .validity()? .cast_nullability(dtype.nullability(), array.len())?; diff --git a/vortex-array/src/arrays/null/compute/cast.rs b/vortex-array/src/arrays/null/compute/cast.rs index be6c73ad7d5..9b8f13550ce 100644 --- a/vortex-array/src/arrays/null/compute/cast.rs +++ b/vortex-array/src/arrays/null/compute/cast.rs @@ -11,10 +11,15 @@ use crate::arrays::ConstantArray; use crate::arrays::Null; use crate::dtype::DType; use crate::scalar::Scalar; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; impl CastReduce for Null { - fn cast(array: ArrayView<'_, Null>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, Null>, + dtype: &DType, + _options: &CastOptions, + ) -> VortexResult> { if !dtype.is_nullable() { vortex_bail!("Cannot cast Null to {}", dtype); } diff --git a/vortex-array/src/arrays/primitive/compute/cast.rs b/vortex-array/src/arrays/primitive/compute/cast.rs index f1c9d3bcdbc..59dbbaa9594 100644 --- a/vortex-array/src/arrays/primitive/compute/cast.rs +++ b/vortex-array/src/arrays/primitive/compute/cast.rs @@ -21,11 +21,13 @@ use crate::dtype::Nullability; use crate::dtype::PType; use crate::match_each_native_ptype; use crate::scalar_fn::fns::cast::CastKernel; +use crate::scalar_fn::fns::cast::CastOptions; impl CastKernel for Primitive { fn cast( array: ArrayView<'_, Primitive>, dtype: &DType, + _options: &CastOptions, ctx: &mut ExecutionCtx, ) -> VortexResult> { let DType::Primitive(new_ptype, new_nullability) = dtype else { diff --git a/vortex-array/src/arrays/struct_/compute/cast.rs b/vortex-array/src/arrays/struct_/compute/cast.rs index 6c9a5f1edca..10284f3e5f7 100644 --- a/vortex-array/src/arrays/struct_/compute/cast.rs +++ b/vortex-array/src/arrays/struct_/compute/cast.rs @@ -17,11 +17,14 @@ use crate::builtins::ArrayBuiltins; use crate::dtype::DType; use crate::scalar::Scalar; use crate::scalar_fn::fns::cast::CastKernel; +use crate::scalar_fn::fns::cast::CastMode; +use crate::scalar_fn::fns::cast::CastOptions; impl CastKernel for Struct { fn cast( array: ArrayView<'_, Struct>, dtype: &DType, + options: &CastOptions, _ctx: &mut ExecutionCtx, ) -> VortexResult> { let Some(target_sdtype) = dtype.as_struct_fields_opt() else { @@ -30,46 +33,59 @@ impl CastKernel for Struct { let source_sdtype = array.struct_fields(); - let fields_match_order = target_sdtype.nfields() == source_sdtype.nfields() - && target_sdtype - .names() - .iter() - .zip(source_sdtype.names().iter()) - .all(|(f1, f2)| f1 == f2); - - let mut cast_fields = Vec::with_capacity(target_sdtype.nfields()); - if fields_match_order { - for (field, target_type) in array.iter_unmasked_fields().zip_eq(target_sdtype.fields()) - { - let cast_field = field.cast(target_type)?; - cast_fields.push(cast_field); + let cast_fields = match options.mode() { + CastMode::ByPosition => { + vortex_ensure!( + target_sdtype.nfields() == source_sdtype.nfields(), + "CAST by position requires source ({}) and target ({}) struct to have the same number of fields", + source_sdtype.nfields(), + target_sdtype.nfields() + ); + array + .iter_unmasked_fields() + .zip_eq(target_sdtype.fields()) + .map(|(field, target_type)| field.cast_opts(target_type, *options)) + .try_collect()? } - } else { - // Re-order, handle fields by value instead. - for (target_name, target_type) in - target_sdtype.names().iter().zip_eq(target_sdtype.fields()) - { - match source_sdtype.find(target_name) { - None => { - // No source field with this name => evolve the schema compatibly. - // If the field is nullable, we add a new ConstantArray field with the type. - vortex_ensure!( - target_type.is_nullable(), - "CAST for struct only supports added nullable fields" - ); - - cast_fields.push( - ConstantArray::new(Scalar::null(target_type), array.len()).into_array(), - ); - } - Some(src_field_idx) => { - // Field exists in source field. Cast it to the target type. - let cast_field = array.unmasked_field(src_field_idx).cast(target_type)?; - cast_fields.push(cast_field); + CastMode::ByName => { + vortex_ensure!( + source_sdtype.names().iter().all_unique(), + "CAST by name requires unique field names in the source struct; \ + use by-position mode for structs with duplicate field names" + ); + vortex_ensure!( + target_sdtype.names().iter().all_unique(), + "CAST by name requires unique field names in the target struct; \ + use by-position mode for structs with duplicate field names" + ); + let mut cast_fields = Vec::with_capacity(target_sdtype.nfields()); + for (target_name, target_type) in + target_sdtype.names().iter().zip_eq(target_sdtype.fields()) + { + match source_sdtype.find(target_name) { + None => { + vortex_ensure!( + target_type.is_nullable(), + "Cannot add non-nullable field '{}' during struct cast", + target_name + ); + cast_fields.push( + ConstantArray::new(Scalar::null(target_type), array.len()) + .into_array(), + ); + } + Some(src_field_idx) => { + cast_fields.push( + array + .unmasked_field(src_field_idx) + .cast_opts(target_type, *options)?, + ); + } } } + cast_fields } - } + }; let validity = array .validity()? @@ -87,12 +103,14 @@ impl CastKernel for Struct { #[cfg(test)] mod tests { + use std::sync::LazyLock; + use rstest::rstest; use vortex_buffer::buffer; + use vortex_session::VortexSession; use crate::IntoArray; - #[expect(deprecated)] - use crate::ToCanonical as _; + use crate::VortexSessionExecute; use crate::arrays::PrimitiveArray; use crate::arrays::StructArray; use crate::arrays::VarBinArray; @@ -104,8 +122,12 @@ mod tests { use crate::dtype::FieldNames; use crate::dtype::Nullability; use crate::dtype::PType; + use crate::session::ArraySession; use crate::validity::Validity; + static SESSION: LazyLock = + LazyLock::new(|| VortexSession::empty().with::()); + #[rstest] #[case(create_test_struct(false))] #[case(create_test_struct(true))] @@ -194,7 +216,10 @@ mod tests { } #[test] - fn cast_duplicate_field_names_to_nullable() { + fn cast_by_position_handles_duplicate_field_names() { + use crate::assert_arrays_eq; + use crate::scalar_fn::fns::cast::CastOptions; + let names = FieldNames::from(["a", "a"]); let field1 = buffer![1i32, 2, 3].into_array(); let field2 = buffer![10i64, 20, 30].into_array(); @@ -206,13 +231,72 @@ mod tests { let result = struct_array .into_array() - .cast(target_dtype.clone()) + .cast_opts(target_dtype.clone(), CastOptions::by_position()) + .unwrap() + .execute::(&mut SESSION.create_execution_ctx()) .unwrap(); assert_eq!(result.dtype(), &target_dtype); assert_eq!(result.len(), 3); - #[expect(deprecated)] - let nfields = result.to_struct().struct_fields().nfields(); - assert_eq!(nfields, 2); + assert_eq!(result.struct_fields().nfields(), 2); + assert_arrays_eq!(result.unmasked_field(0), buffer![1i32, 2, 3].into_array()); + assert_arrays_eq!( + result.unmasked_field(1), + buffer![10i64, 20, 30].into_array() + ); + } + + #[test] + fn cast_by_name_duplicate_source_names_fails() { + use crate::scalar_fn::fns::cast::CastOptions; + + let source = StructArray::try_new( + FieldNames::from(["a", "a"]), + vec![buffer![1i32].into_array(), buffer![10i64].into_array()], + 1, + Validity::NonNullable, + ) + .unwrap(); + + let target = source.dtype().as_nullable(); + + let err = source + .into_array() + .cast_opts(target, CastOptions::by_name()) + .unwrap_err(); + assert!( + err.to_string().contains("unique"), + "expected uniqueness error, got: {err}" + ); + } + + #[test] + fn cast_by_name_duplicate_target_names_fails() { + use crate::scalar_fn::fns::cast::CastOptions; + + let source = StructArray::try_new( + FieldNames::from(["a", "b"]), + vec![buffer![1i32].into_array(), buffer![10i64].into_array()], + 1, + Validity::NonNullable, + ) + .unwrap(); + + let target = DType::struct_( + [ + ("a", DType::Primitive(PType::I32, Nullability::NonNullable)), + ("a", DType::Primitive(PType::I64, Nullability::NonNullable)), + ], + Nullability::NonNullable, + ); + + let err = source + .into_array() + .cast_opts(target, CastOptions::by_name()) + .unwrap_err(); + assert!( + err.to_string().contains("unique"), + "expected uniqueness error, got: {err}" + ); } #[test] @@ -241,8 +325,79 @@ mod tests { .unwrap(); assert_eq!(result.dtype(), &target_dtype); assert_eq!(result.len(), 3); - #[expect(deprecated)] - let nfields = result.to_struct().struct_fields().nfields(); + let nfields = result + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap() + .struct_fields() + .nfields(); assert_eq!(nfields, 3); } + + #[test] + fn cast_by_position_renames_fields() { + use crate::assert_arrays_eq; + use crate::scalar_fn::fns::cast::CastOptions; + + // Source: {a, b}, Target: {x, y} - same number of fields, different names. + let source = StructArray::try_new( + FieldNames::from(["a", "b"]), + vec![ + buffer![1i32, 2, 3].into_array(), + buffer![10i64, 20, 30].into_array(), + ], + 3, + Validity::NonNullable, + ) + .unwrap(); + + let target = DType::struct_( + [ + ("x", DType::Primitive(PType::I32, Nullability::NonNullable)), + ("y", DType::Primitive(PType::I64, Nullability::NonNullable)), + ], + Nullability::NonNullable, + ); + + let result = source + .into_array() + .cast_opts(target.clone(), CastOptions::by_position()) + .unwrap() + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap(); + + assert_eq!(result.dtype(), &target); + assert_arrays_eq!( + result.unmasked_field_by_name("x").unwrap(), + buffer![1i32, 2, 3].into_array() + ); + assert_arrays_eq!( + result.unmasked_field_by_name("y").unwrap(), + buffer![10i64, 20, 30].into_array() + ); + } + + #[test] + fn cast_by_position_field_count_mismatch_fails() { + use crate::scalar_fn::fns::cast::CastOptions; + + let source = StructArray::try_new( + FieldNames::from(["a", "b"]), + vec![buffer![1i32].into_array(), buffer![10i64].into_array()], + 1, + Validity::NonNullable, + ) + .unwrap(); + + let target = DType::struct_( + [("x", DType::Primitive(PType::I32, Nullability::NonNullable))], + Nullability::NonNullable, + ); + + assert!( + source + .into_array() + .cast_opts(target, CastOptions::by_position()) + .is_err() + ); + } } diff --git a/vortex-array/src/arrays/struct_/compute/rules.rs b/vortex-array/src/arrays/struct_/compute/rules.rs index 8a802969d39..e76504dad64 100644 --- a/vortex-array/src/arrays/struct_/compute/rules.rs +++ b/vortex-array/src/arrays/struct_/compute/rules.rs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: Copyright the Vortex contributors +use itertools::Itertools; use vortex_error::VortexResult; use vortex_error::vortex_ensure; use vortex_error::vortex_err; @@ -22,6 +23,7 @@ use crate::optimizer::rules::ArrayParentReduceRule; use crate::optimizer::rules::ParentRuleSet; use crate::scalar_fn::EmptyOptions; use crate::scalar_fn::fns::cast::Cast; +use crate::scalar_fn::fns::cast::CastMode; use crate::scalar_fn::fns::get_item::GetItem; use crate::scalar_fn::fns::mask::Mask; use crate::scalar_fn::fns::mask::MaskReduceAdaptor; @@ -37,10 +39,10 @@ pub(crate) const PARENT_RULES: ParentRuleSet = ParentRuleSet::new(&[ /// Rule to push down cast into struct fields. /// -/// TODO(joe/rob): should be have this in casts. -/// -/// This rule supports schema evolution by allowing new nullable fields to be added -/// at the end of the struct, filled with null values. +/// In [`CastMode::ByName`] this also supports schema evolution by allowing new nullable +/// fields to appear in the target type (filled with nulls) and source-only fields to be +/// dropped. In [`CastMode::ByPosition`] the source and target struct must have the same +/// number of fields and they are matched positionally regardless of name. #[derive(Debug)] struct StructCastPushDownRule; impl ArrayParentReduceRule for StructCastPushDownRule { @@ -52,41 +54,74 @@ impl ArrayParentReduceRule for StructCastPushDownRule { parent: ScalarFnArrayView, _child_idx: usize, ) -> VortexResult> { - let Some(target_fields) = parent.options.as_struct_fields_opt() else { + let dtype = parent.options.target(); + let options = parent.options.options(); + let Some(target_fields) = dtype.as_struct_fields_opt() else { return Ok(None); }; - let mut new_fields = Vec::with_capacity(target_fields.nfields()); - for (target_name, target_dtype) in target_fields.names().iter().zip(target_fields.fields()) - { - match array.unmasked_field_by_name(target_name).ok() { - Some(field) => { - new_fields.push(field.cast(target_dtype)?); - } - None => { - // Not found - create NULL array (schema evolution) - vortex_ensure!( - target_dtype.is_nullable(), - "Cannot add non-nullable field '{}' during struct cast", - target_name - ); - new_fields.push( - ConstantArray::new(crate::scalar::Scalar::null(target_dtype), array.len()) - .into_array(), - ); + let source_fields = array.struct_fields(); + + let new_fields = match options.mode() { + CastMode::ByPosition => { + vortex_ensure!( + source_fields.nfields() == target_fields.nfields(), + "CAST by position requires source ({}) and target ({}) struct to have the same number of fields", + source_fields.nfields(), + target_fields.nfields() + ); + (0..source_fields.nfields()) + .zip_eq(target_fields.fields()) + .map(|(src_idx, target_dtype)| { + array + .unmasked_field(src_idx) + .cast_opts(target_dtype, *options) + }) + .try_collect()? + } + CastMode::ByName => { + vortex_ensure!( + source_fields.names().iter().all_unique(), + "CAST by name requires unique field names in the source struct; \ + use by-position mode for structs with duplicate field names" + ); + vortex_ensure!( + target_fields.names().iter().all_unique(), + "CAST by name requires unique field names in the target struct; \ + use by-position mode for structs with duplicate field names" + ); + let mut new_fields = Vec::with_capacity(target_fields.nfields()); + for (target_name, target_dtype) in + target_fields.names().iter().zip(target_fields.fields()) + { + match array.unmasked_field_by_name(target_name).ok() { + Some(field) => { + new_fields.push(field.cast_opts(target_dtype, *options)?); + } + None => { + vortex_ensure!( + target_dtype.is_nullable(), + "Cannot add non-nullable field '{}' during struct cast", + target_name + ); + new_fields.push( + ConstantArray::new( + crate::scalar::Scalar::null(target_dtype), + array.len(), + ) + .into_array(), + ); + } + } } + new_fields } - } - - let validity = if parent.options.is_nullable() { - array.validity()?.into_nullable() - } else { - array - .validity()? - .into_non_nullable(array.len()) - .ok_or_else(|| vortex_err!("Failed to cast nullable struct to non-nullable"))? }; + let validity = array + .validity()? + .cast_nullability(dtype.nullability(), array.len())?; + let new_struct = unsafe { StructArray::new_unchecked(new_fields, target_fields.clone(), array.len(), validity) }; @@ -144,25 +179,31 @@ impl ArrayParentReduceRule for StructGetItemRule { #[cfg(test)] mod tests { + use std::sync::LazyLock; + use vortex_buffer::buffer; + use vortex_session::VortexSession; use crate::IntoArray; + use crate::VortexSessionExecute; use crate::arrays::StructArray; use crate::arrays::VarBinViewArray; use crate::arrays::struct_::StructArrayExt; use crate::arrays::struct_::compute::rules::ConstantArray; use crate::assert_arrays_eq; use crate::builtins::ArrayBuiltins; - #[expect(deprecated)] - use crate::canonical::ToCanonical as _; use crate::dtype::DType; use crate::dtype::FieldNames; use crate::dtype::Nullability; use crate::dtype::PType; use crate::dtype::StructFields; use crate::scalar::Scalar; + use crate::session::ArraySession; use crate::validity::Validity; + static SESSION: LazyLock = + LazyLock::new(|| VortexSession::empty().with::()); + #[test] fn test_struct_cast_field_reorder() { // Source: {a, b}, Target: {c, b, a} - reordered + new null field @@ -188,8 +229,12 @@ mod tests { // Use `ArrayBuiltins::cast` which goes through the optimizer and applies // `StructCastPushDownRule`. - #[expect(deprecated)] - let result = source.into_array().cast(target).unwrap().to_struct(); + let result = source + .into_array() + .cast(target) + .unwrap() + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap(); assert_arrays_eq!( result.unmasked_field_by_name("a").unwrap(), VarBinViewArray::from_iter_nullable_str([Some("A")]) @@ -257,8 +302,12 @@ mod tests { Nullability::NonNullable, ); - #[expect(deprecated)] - let result = source.into_array().cast(target).unwrap().to_struct(); + let result = source + .into_array() + .cast(target) + .unwrap() + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap(); assert_eq!(result.unmasked_fields().len(), 2); assert_arrays_eq!( result.unmasked_field_by_name("a").unwrap(), @@ -289,8 +338,13 @@ mod tests { Nullability::NonNullable, ); - #[expect(deprecated)] - let result = source.into_array().cast(target).unwrap().to_struct(); + let result = source + .into_array() + .cast(target) + .unwrap() + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap(); + assert_eq!( result.unmasked_field_by_name("val").unwrap().dtype(), &DType::Primitive(PType::I64, Nullability::NonNullable) @@ -325,4 +379,169 @@ mod tests { assert!(source.into_array().cast(target).is_err()); } + + #[test] + fn cast_struct_by_position_ignores_names() { + use crate::scalar_fn::fns::cast::CastOptions; + + // Source: {a, b}, Target: {x, y} - by_position should match by index, not name. + let source = StructArray::try_new( + FieldNames::from(["a", "b"]), + vec![ + buffer![1i32, 2, 3].into_array(), + buffer![10i64, 20, 30].into_array(), + ], + 3, + Validity::NonNullable, + ) + .unwrap(); + + let target = DType::Struct( + StructFields::new( + FieldNames::from(["x", "y"]), + vec![ + DType::Primitive(PType::I32, Nullability::NonNullable), + DType::Primitive(PType::I64, Nullability::NonNullable), + ], + ), + Nullability::NonNullable, + ); + + let result = source + .into_array() + .cast_opts(target.clone(), CastOptions::by_position()) + .unwrap() + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap(); + + assert_eq!(result.dtype(), &target); + assert_arrays_eq!( + result.unmasked_field_by_name("x").unwrap(), + buffer![1i32, 2, 3].into_array() + ); + assert_arrays_eq!( + result.unmasked_field_by_name("y").unwrap(), + buffer![10i64, 20, 30].into_array() + ); + } + + #[test] + fn cast_struct_by_position_field_count_mismatch_fails() { + use crate::scalar_fn::fns::cast::CastOptions; + + let source = StructArray::try_new( + FieldNames::from(["a", "b"]), + vec![buffer![1i32].into_array(), buffer![10i64].into_array()], + 1, + Validity::NonNullable, + ) + .unwrap(); + + let target = DType::Struct( + StructFields::new( + FieldNames::from(["x"]), + vec![DType::Primitive(PType::I32, Nullability::NonNullable)], + ), + Nullability::NonNullable, + ); + + assert!( + source + .into_array() + .cast_opts(target, CastOptions::by_position()) + .is_err() + ); + } + + #[test] + fn cast_struct_by_position_handles_duplicate_field_names() { + use crate::scalar_fn::fns::cast::CastOptions; + + // Source has duplicate field names; by_position matches positionally, so both fields + // retain their original data (no collision). + let source = StructArray::try_new( + FieldNames::from(["a", "a"]), + vec![ + buffer![1i32, 2, 3].into_array(), + buffer![10i64, 20, 30].into_array(), + ], + 3, + Validity::NonNullable, + ) + .unwrap(); + + let target = source.dtype().as_nullable(); + + let result = source + .into_array() + .cast_opts(target.clone(), CastOptions::by_position()) + .unwrap() + .execute::(&mut SESSION.create_execution_ctx()) + .unwrap(); + assert_eq!(result.dtype(), &target); + assert_arrays_eq!(result.unmasked_field(0), buffer![1i32, 2, 3].into_array()); + assert_arrays_eq!( + result.unmasked_field(1), + buffer![10i64, 20, 30].into_array() + ); + } + + #[test] + fn cast_struct_by_name_duplicate_source_names_fails() { + use crate::scalar_fn::fns::cast::CastOptions; + + // `find` cannot disambiguate duplicate source names, so by_name must reject them. + let source = StructArray::try_new( + FieldNames::from(["a", "a"]), + vec![buffer![1i32].into_array(), buffer![10i64].into_array()], + 1, + Validity::NonNullable, + ) + .unwrap(); + + let target = source.dtype().as_nullable(); + + let err = source + .into_array() + .cast_opts(target, CastOptions::by_name()) + .unwrap_err(); + assert!( + err.to_string().contains("unique"), + "expected uniqueness error, got: {err}" + ); + } + + #[test] + fn cast_struct_by_name_duplicate_target_names_fails() { + use crate::scalar_fn::fns::cast::CastOptions; + + // Duplicate target names would collapse silently under by_name, so we reject them. + let source = StructArray::try_new( + FieldNames::from(["a", "b"]), + vec![buffer![1i32].into_array(), buffer![10i64].into_array()], + 1, + Validity::NonNullable, + ) + .unwrap(); + + let target = DType::Struct( + StructFields::new( + FieldNames::from(["a", "a"]), + vec![ + DType::Primitive(PType::I32, Nullability::NonNullable), + DType::Primitive(PType::I64, Nullability::NonNullable), + ], + ), + Nullability::NonNullable, + ); + + let err = source + .into_array() + .cast_opts(target, CastOptions::by_name()) + .unwrap_err(); + assert!( + err.to_string().contains("unique"), + "expected uniqueness error, got: {err}" + ); + } } diff --git a/vortex-array/src/arrays/varbin/compute/cast.rs b/vortex-array/src/arrays/varbin/compute/cast.rs index 6b02283aec8..5ad1b289928 100644 --- a/vortex-array/src/arrays/varbin/compute/cast.rs +++ b/vortex-array/src/arrays/varbin/compute/cast.rs @@ -10,10 +10,15 @@ use crate::arrays::VarBin; use crate::arrays::VarBinArray; use crate::arrays::varbin::VarBinArrayExt; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; impl CastReduce for VarBin { - fn cast(array: ArrayView<'_, VarBin>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, VarBin>, + dtype: &DType, + _options: &CastOptions, + ) -> VortexResult> { if !array.dtype().eq_ignore_nullability(dtype) { return Ok(None); } diff --git a/vortex-array/src/arrays/varbinview/compute/cast.rs b/vortex-array/src/arrays/varbinview/compute/cast.rs index a8e649f52e4..545914459f5 100644 --- a/vortex-array/src/arrays/varbinview/compute/cast.rs +++ b/vortex-array/src/arrays/varbinview/compute/cast.rs @@ -11,10 +11,15 @@ use crate::array::ArrayView; use crate::arrays::VarBinView; use crate::arrays::VarBinViewArray; use crate::dtype::DType; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::cast::CastReduce; impl CastReduce for VarBinView { - fn cast(array: ArrayView<'_, VarBinView>, dtype: &DType) -> VortexResult> { + fn cast( + array: ArrayView<'_, VarBinView>, + dtype: &DType, + _options: &CastOptions, + ) -> VortexResult> { if !array.dtype().eq_ignore_nullability(dtype) { return Ok(None); } diff --git a/vortex-array/src/builtins.rs b/vortex-array/src/builtins.rs index dcbe934097e..93c362a4fcf 100644 --- a/vortex-array/src/builtins.rs +++ b/vortex-array/src/builtins.rs @@ -26,6 +26,8 @@ use crate::scalar_fn::fns::between::Between; use crate::scalar_fn::fns::between::BetweenOptions; use crate::scalar_fn::fns::binary::Binary; use crate::scalar_fn::fns::cast::Cast; +use crate::scalar_fn::fns::cast::CastFnOptions; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::fill_null::FillNull; use crate::scalar_fn::fns::get_item::GetItem; use crate::scalar_fn::fns::is_not_null::IsNotNull; @@ -38,9 +40,16 @@ use crate::scalar_fn::fns::zip::Zip; /// A collection of built-in scalar functions that can be applied to expressions or arrays. pub trait ExprBuiltins: Sized { - /// Cast to the given data type. + /// Cast to the given data type using by-name field matching (the default). + /// + /// For positional cast, use [`cast_opts`](Self::cast_opts) with + /// [`CastOptions::by_position`]. fn cast(&self, dtype: DType) -> VortexResult; + /// Cast to the given data type with explicit [`CastOptions`]. Use this when positional + /// field matching is required. + fn cast_opts(&self, dtype: DType, options: CastOptions) -> VortexResult; + /// Replace null values with the given fill value. fn fill_null(&self, fill_value: Expression) -> VortexResult; @@ -73,7 +82,11 @@ pub trait ExprBuiltins: Sized { impl ExprBuiltins for Expression { fn cast(&self, dtype: DType) -> VortexResult { - Cast.try_new_expr(dtype, [self.clone()]) + self.cast_opts(dtype, CastOptions::by_name()) + } + + fn cast_opts(&self, dtype: DType, options: CastOptions) -> VortexResult { + Cast.try_new_expr(CastFnOptions::new(dtype, options), [self.clone()]) } fn fill_null(&self, fill_value: Expression) -> VortexResult { @@ -114,9 +127,16 @@ impl ExprBuiltins for Expression { } pub trait ArrayBuiltins: Sized { - /// Cast to the given data type. + /// Cast to the given data type using by-name field matching (the default). + /// + /// For positional cast, use [`cast_opts`](Self::cast_opts) with + /// [`CastOptions::by_position`]. fn cast(&self, dtype: DType) -> VortexResult; + /// Cast to the given data type with explicit [`CastOptions`]. Use this when positional + /// field matching is required. + fn cast_opts(&self, dtype: DType, options: CastOptions) -> VortexResult; + /// Replace null values with the given fill value. fn fill_null(&self, fill_value: impl Into) -> VortexResult; @@ -157,11 +177,19 @@ pub trait ArrayBuiltins: Sized { impl ArrayBuiltins for ArrayRef { fn cast(&self, dtype: DType) -> VortexResult { + self.cast_opts(dtype, CastOptions::by_name()) + } + + fn cast_opts(&self, dtype: DType, options: CastOptions) -> VortexResult { if self.dtype() == &dtype { return Ok(self.clone()); } - Cast.try_new_array(self.len(), dtype, [self.clone()])? - .optimize() + Cast.try_new_array( + self.len(), + CastFnOptions::new(dtype, options), + [self.clone()], + )? + .optimize() } fn fill_null(&self, fill_value: impl Into) -> VortexResult { diff --git a/vortex-array/src/expr/exprs.rs b/vortex-array/src/expr/exprs.rs index fb8d2f0cb77..95ea517dc3c 100644 --- a/vortex-array/src/expr/exprs.rs +++ b/vortex-array/src/expr/exprs.rs @@ -24,6 +24,8 @@ use crate::scalar_fn::fns::binary::Binary; use crate::scalar_fn::fns::case_when::CaseWhen; use crate::scalar_fn::fns::case_when::CaseWhenOptions; use crate::scalar_fn::fns::cast::Cast; +use crate::scalar_fn::fns::cast::CastFnOptions; +use crate::scalar_fn::fns::cast::CastOptions; use crate::scalar_fn::fns::dynamic::DynamicComparison; use crate::scalar_fn::fns::dynamic::DynamicComparisonExpr; use crate::scalar_fn::fns::dynamic::Rhs; @@ -516,9 +518,10 @@ pub fn pack( // ---- Cast ---- -/// Creates an expression that casts values to a target data type. +/// Creates an expression that casts values to a target data type, matching struct fields by name. /// -/// Converts the input expression's values to the specified target type. +/// This is the default cast behavior. Positional cast must be requested explicitly via +/// [`cast_opts`] with [`CastOptions::by_position`]. /// /// ```rust /// # use vortex_array::dtype::{DType, Nullability, PType}; @@ -526,7 +529,25 @@ pub fn pack( /// let expr = cast(root(), DType::Primitive(PType::I64, Nullability::NonNullable)); /// ``` pub fn cast(child: Expression, target: DType) -> Expression { - Cast.try_new_expr(target, [child]) + cast_opts(child, target, CastOptions::by_name()) +} + +/// Creates an expression that casts values to a target data type with explicit [`CastOptions`]. +/// +/// Use this when you need positional cast semantics: +/// +/// ```rust +/// # use vortex_array::dtype::{DType, Nullability, PType}; +/// # use vortex_array::expr::{cast_opts, root}; +/// # use vortex_array::scalar_fn::fns::cast::CastOptions; +/// let expr = cast_opts( +/// root(), +/// DType::Primitive(PType::I64, Nullability::NonNullable), +/// CastOptions::by_position(), +/// ); +/// ``` +pub fn cast_opts(child: Expression, target: DType, options: CastOptions) -> Expression { + Cast.try_new_expr(CastFnOptions::new(target, options), [child]) .vortex_expect("Failed to create Cast expression") } diff --git a/vortex-array/src/scalar/cast.rs b/vortex-array/src/scalar/cast.rs index a153b93373e..2c43baf1059 100644 --- a/vortex-array/src/scalar/cast.rs +++ b/vortex-array/src/scalar/cast.rs @@ -10,42 +10,49 @@ use vortex_error::vortex_ensure; use crate::dtype::DType; use crate::scalar::Scalar; +use crate::scalar_fn::fns::cast::CastOptions; impl Scalar { - /// Cast this scalar to another data type. + /// Cast this scalar to another data type using by-name field matching (the default). + /// + /// For positional cast, use [`cast_opts`](Self::cast_opts) with + /// [`CastOptions::by_position`]. /// /// # Errors /// /// Returns an error if the cast is not supported or if a null value is cast to a non-nullable /// type. pub fn cast(&self, target_dtype: &DType) -> VortexResult { - // If the types are the same, return a clone. + self.cast_opts(target_dtype, CastOptions::by_name()) + } + + /// Cast this scalar to another data type, honoring the given [`CastOptions`]. + /// + /// Only struct scalars actually use the options today; for all other source types the cast + /// behavior is identical to [`Self::cast`]. + pub fn cast_opts(&self, target_dtype: &DType, options: CastOptions) -> VortexResult { if self.dtype() == target_dtype { return Ok(self.clone()); } - // Check for solely nullability casting. if self.dtype().eq_ignore_nullability(target_dtype) { - // Cast from non-nullable to nullable or vice versa. - // The `try_new` will handle nullability checks. return Scalar::try_new(target_dtype.clone(), self.value().cloned()); } - // Null can be cast into any nullable type as null. - // Note that the `matches` clause is technically unnecessary here, just protective. if self.value().is_none() || matches!(self.dtype(), DType::Null) { vortex_ensure!( target_dtype.is_nullable(), "Cannot cast null to {target_dtype}: target type is non-nullable" ); - return Scalar::try_new(target_dtype.clone(), self.value().cloned()); } // TODO(connor): This isn't really correct for extension types. // If the target is an extension type, then we want to cast to its storage type. if let Some(ext_dtype) = target_dtype.as_extension_opt() { - let cast_storage_scalar_value = self.cast(ext_dtype.storage_dtype())?.into_value(); + let cast_storage_scalar_value = self + .cast_opts(ext_dtype.storage_dtype(), options)? + .into_value(); return Scalar::try_new(target_dtype.clone(), cast_storage_scalar_value); } @@ -56,7 +63,7 @@ impl Scalar { DType::Decimal(..) => self.as_decimal().cast(target_dtype), DType::Utf8(_) => self.as_utf8().cast(target_dtype), DType::Binary(_) => self.as_binary().cast(target_dtype), - DType::Struct(..) => self.as_struct().cast(target_dtype), + DType::Struct(..) => self.as_struct().cast_opts(target_dtype, options), DType::List(..) | DType::FixedSizeList(..) => self.as_list().cast(target_dtype), DType::Extension(..) => self.as_extension().cast(target_dtype), DType::Variant(_) => vortex_bail!("Variant scalars can't be cast to {target_dtype}"), diff --git a/vortex-array/src/scalar/typed_view/struct_.rs b/vortex-array/src/scalar/typed_view/struct_.rs index 93b796f055f..8af4036c85e 100644 --- a/vortex-array/src/scalar/typed_view/struct_.rs +++ b/vortex-array/src/scalar/typed_view/struct_.rs @@ -22,6 +22,8 @@ use crate::dtype::FieldNames; use crate::dtype::StructFields; use crate::scalar::Scalar; use crate::scalar::ScalarValue; +use crate::scalar_fn::fns::cast::CastMode; +use crate::scalar_fn::fns::cast::CastOptions; /// A scalar value representing a struct with named fields. /// @@ -196,50 +198,112 @@ impl<'a> StructScalar<'a> { ) } - /// Casts this struct scalar to another struct type. + /// Casts this struct scalar to another struct type using by-name field matching (the default). + /// + /// For positional cast, use [`cast_opts`](Self::cast_opts) with + /// [`CastOptions::by_position`]. /// /// # Errors /// - /// Returns an error if the target type is not a struct or if the number of fields don't match. + /// Returns an error if the target type is not a struct, or if the cast is otherwise invalid + /// per the by-name cast rules (see [`Self::cast_opts`]). pub fn cast(&self, dtype: &DType) -> VortexResult { - let DType::Struct(st, _) = dtype else { + self.cast_opts(dtype, CastOptions::by_name()) + } + + /// Casts this struct scalar to another struct type, honoring the given [`CastOptions`]. + /// + /// In [`CastMode::ByPosition`] the source and target must have the same number of fields and + /// they are matched positionally regardless of name. In [`CastMode::ByName`] both source and + /// target field names must be unique; fields are looked up by name and target-only fields may + /// be added as null if nullable (schema evolution). + /// + /// # Errors + /// + /// Returns an error if the target type is not a struct, if by-position counts differ, if + /// by-name finds duplicate names, or if a missing by-name field is non-nullable. + pub fn cast_opts(&self, dtype: &DType, options: CastOptions) -> VortexResult { + let DType::Struct(target_sf, _) = dtype else { vortex_bail!( "Cannot cast struct to {}: struct can only be cast to struct", dtype ) }; - let own_st = self.struct_fields(); + let source_sf = self.struct_fields(); - if st.fields().len() != own_st.fields().len() { - vortex_bail!( - "Cannot cast between structs with different number of fields: {} and {}", - own_st.fields().len(), - st.fields().len() - ); - } + let Some(source_fs) = self.fields else { + // Null struct scalar is null in any struct target if the target is nullable. + return Ok(Scalar::null(dtype.clone())); + }; - if let Some(fs) = self.fields { - let fields = fs - .iter() - .enumerate() - .map(|(i, f)| { - Scalar::try_new( - own_st - .field_by_index(i) - .vortex_expect("Iterating over scalar fields"), - f.clone(), - )? - .cast( - &st.field_by_index(i) - .vortex_expect("Iterating over scalar fields"), + let target_values: Vec> = match options.mode() { + CastMode::ByPosition => { + if target_sf.nfields() != source_sf.nfields() { + vortex_bail!( + "CAST by position requires source ({}) and target ({}) struct to have the same number of fields", + source_sf.nfields(), + target_sf.nfields() + ); + } + source_fs + .iter() + .zip_eq(source_sf.fields().zip_eq(target_sf.fields())) + .map(|(v, (src_dt, tgt_dt))| { + // SAFETY: dtype matches the scalar value provenance. + let src_scalar = unsafe { Scalar::new_unchecked(src_dt, v.clone()) }; + src_scalar + .cast_opts(&tgt_dt, options) + .map(|s| s.into_value()) + }) + .collect::>>()? + } + CastMode::ByName => { + if !source_sf.names().iter().all_unique() { + vortex_bail!( + "CAST by name requires unique field names in the source struct; \ + use by-position mode for structs with duplicate field names" + ); + } + if !target_sf.names().iter().all_unique() { + vortex_bail!( + "CAST by name requires unique field names in the target struct; \ + use by-position mode for structs with duplicate field names" + ); + } + target_sf + .names() + .iter() + .zip_eq(target_sf.fields()) + .map( + |(target_name, target_dtype)| match source_sf.find(target_name) { + Some(src_idx) => { + let src_dt = source_sf + .field_by_index(src_idx) + .vortex_expect("source field index valid"); + // SAFETY: dtype matches the scalar value provenance. + let src_scalar = unsafe { + Scalar::new_unchecked(src_dt, source_fs[src_idx].clone()) + }; + src_scalar + .cast_opts(&target_dtype, options) + .map(|s| s.into_value()) + } + None => { + if !target_dtype.is_nullable() { + vortex_bail!( + "Cannot add non-nullable field '{}' during struct cast", + target_name + ); + } + Ok(None) + } + }, ) - .map(|s| s.into_value()) - }) - .collect::>>()?; - Scalar::try_new(dtype.clone(), Some(ScalarValue::List(fields))) - } else { - Ok(Scalar::null(dtype.clone())) - } + .collect::>>()? + } + }; + + Scalar::try_new(dtype.clone(), Some(ScalarValue::List(target_values))) } /// Projects this struct scalar to include only the specified fields. diff --git a/vortex-array/src/scalar_fn/fns/cast/kernel.rs b/vortex-array/src/scalar_fn/fns/cast/kernel.rs index ca9783cc22e..bb35d7a7e22 100644 --- a/vortex-array/src/scalar_fn/fns/cast/kernel.rs +++ b/vortex-array/src/scalar_fn/fns/cast/kernel.rs @@ -14,6 +14,7 @@ use crate::kernel::ExecuteParentKernel; use crate::matcher::Matcher; use crate::optimizer::rules::ArrayParentReduceRule; use crate::scalar_fn::fns::cast::Cast; +use crate::scalar_fn::fns::cast::CastOptions; /// Reduce rule for cast: restructure the array without reading buffers. /// @@ -23,7 +24,13 @@ use crate::scalar_fn::fns::cast::Cast; /// /// Returns `Ok(None)` if the rule doesn't apply to this array/dtype combination. pub trait CastReduce: VTable { - fn cast(array: ArrayView<'_, Self>, dtype: &DType) -> VortexResult>; + /// Attempt to restructure the array to `dtype` using the given `options`, without reading + /// buffers. + fn cast( + array: ArrayView<'_, Self>, + dtype: &DType, + options: &CastOptions, + ) -> VortexResult>; } /// Execute kernel for cast: perform the actual value conversion, potentially reading buffers. @@ -33,9 +40,11 @@ pub trait CastReduce: VTable { /// /// Returns `Ok(None)` if this kernel cannot handle the given dtype conversion. pub trait CastKernel: VTable { + /// Perform the actual value conversion to `dtype` using the given `options`. fn cast( array: ArrayView<'_, Self>, dtype: &DType, + options: &CastOptions, ctx: &mut ExecutionCtx, ) -> VortexResult>; } @@ -56,11 +65,12 @@ where parent: ScalarFnArrayView<'_, Cast>, _child_idx: usize, ) -> VortexResult> { - let dtype = parent.options; + let instance = parent.options; + let dtype = instance.target(); if array.dtype() == dtype { return Ok(Some(array.array().clone())); } - ::cast(array, dtype) + ::cast(array, dtype, instance.options()) } } @@ -81,10 +91,11 @@ where _child_idx: usize, ctx: &mut ExecutionCtx, ) -> VortexResult> { - let dtype = parent.options; + let instance = parent.options; + let dtype = instance.target(); if array.dtype() == dtype { return Ok(Some(array.array().clone())); } - ::cast(array, dtype, ctx) + ::cast(array, dtype, instance.options(), ctx) } } diff --git a/vortex-array/src/scalar_fn/fns/cast/mod.rs b/vortex-array/src/scalar_fn/fns/cast/mod.rs index 4bb21961552..e43f68ee8f8 100644 --- a/vortex-array/src/scalar_fn/fns/cast/mod.rs +++ b/vortex-array/src/scalar_fn/fns/cast/mod.rs @@ -3,6 +3,7 @@ mod kernel; +use std::fmt::Display; use std::fmt::Formatter; pub use kernel::*; @@ -49,17 +50,142 @@ use crate::scalar_fn::ScalarFnVTable; #[derive(Clone)] pub struct Cast; +/// How a cast matches up values between the input and target types. +/// +/// Most relevant when casting between struct types, where matching fields by name allows +/// reordering and schema evolution, while matching by position requires the source and target +/// struct to have the same field order. +/// +/// By-name is the default cast behavior and does not need to be requested explicitly. By-position +/// must always be opted into via [`CastOptions::by_position`]. +#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] +pub enum CastMode { + /// Match fields by name. This is the implicit default of [`cast`](crate::expr::cast). + ByName, + /// Match fields by position. Requires explicit [`CastOptions::by_position`]. + ByPosition, +} + +impl CastMode { + /// A short string identifier for this mode, used in displays. + pub fn name(&self) -> &'static str { + match self { + CastMode::ByPosition => "by_position", + CastMode::ByName => "by_name", + } + } +} + +impl From for pb::CastMode { + fn from(mode: CastMode) -> Self { + match mode { + CastMode::ByPosition => pb::CastMode::ByPosition, + CastMode::ByName => pb::CastMode::ByName, + } + } +} + +impl From for CastMode { + fn from(mode: pb::CastMode) -> Self { + match mode { + pb::CastMode::ByPosition => CastMode::ByPosition, + pb::CastMode::ByName => CastMode::ByName, + } + } +} + +/// Options controlling the semantics of a cast operation. +/// +/// The target data type is passed separately alongside these options; `CastOptions` captures +/// only knobs that tweak *how* the cast is performed. +/// +/// `CastOptions` intentionally has no `Default`: by-name is already the default behavior of the +/// plain [`cast`](crate::expr::cast) helpers, so callers that pass options must be explicit about +/// which mode they want — typically [`CastOptions::by_position`] when they need positional +/// semantics. +#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] +pub struct CastOptions { + mode: CastMode, +} + +impl CastOptions { + /// Create a new [`CastOptions`] with the given matching mode. + pub fn new(mode: CastMode) -> Self { + Self { mode } + } + + /// Options that match struct fields by name. This is the same behavior as + /// [`cast`](crate::expr::cast), and is exposed so callers can be explicit about the cast + /// mode (e.g. in tests) or pass [`CastOptions`] generically. + pub fn by_name() -> Self { + Self::new(CastMode::ByName) + } + + /// Options that match struct fields by position. Positional cast must always be requested + /// explicitly; there is no default-options path that selects this mode. + pub fn by_position() -> Self { + Self::new(CastMode::ByPosition) + } + + /// The field-matching mode of this cast. + pub fn mode(&self) -> CastMode { + self.mode + } +} + +impl Display for CastOptions { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str(self.mode.name()) + } +} + +/// Combined options stored on a `vortex.cast` [`ScalarFnVTable`] instance: the target +/// data type plus the [`CastOptions`] controlling how the cast is performed. +#[derive(Clone, Hash, Eq, PartialEq, Debug)] +pub struct CastFnOptions { + target: DType, + options: CastOptions, +} + +impl CastFnOptions { + /// Create a new [`CastFnOptions`] from a target type and cast options. + pub fn new(target: DType, options: CastOptions) -> Self { + Self { target, options } + } + + /// The target data type of this cast. + pub fn target(&self) -> &DType { + &self.target + } + + /// The [`CastOptions`] that govern how the cast is performed. + pub fn options(&self) -> &CastOptions { + &self.options + } +} + +impl Display for CastFnOptions { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + // Omit the mode for the implicit default (by-name) to keep the common case terse. + match self.options.mode { + CastMode::ByName => write!(f, "{}", self.target), + CastMode::ByPosition => write!(f, "{}: {}", self.options, self.target), + } + } +} + impl ScalarFnVTable for Cast { - type Options = DType; + type Options = CastFnOptions; fn id(&self) -> ScalarFnId { ScalarFnId::new("vortex.cast") } - fn serialize(&self, dtype: &DType) -> VortexResult>> { + fn serialize(&self, instance: &CastFnOptions) -> VortexResult>> { Ok(Some( pb::CastOpts { - target: Some(dtype.try_into()?), + target: Some((&instance.target).try_into()?), + mode: pb::CastMode::from(instance.options.mode()) as i32, } .encode_to_vec(), )) @@ -67,84 +193,98 @@ impl ScalarFnVTable for Cast { fn deserialize( &self, - _metadata: &[u8], + metadata: &[u8], session: &VortexSession, ) -> VortexResult { - let proto = pb::CastOpts::decode(_metadata)?.target; - DType::from_proto( + let proto = pb::CastOpts::decode(metadata)?; + let mode = CastMode::from(pb::CastMode::try_from(proto.mode).map_err(|_| { + vortex_err!("Unknown cast mode value {} in Cast expression", proto.mode) + })?); + let target = DType::from_proto( proto + .target .as_ref() .ok_or_else(|| vortex_err!("Missing target dtype in Cast expression"))?, session, - ) + )?; + Ok(CastFnOptions::new(target, CastOptions::new(mode))) } - fn arity(&self, _options: &DType) -> Arity { + fn arity(&self, _options: &CastFnOptions) -> Arity { Arity::Exact(1) } - fn child_name(&self, _instance: &DType, child_idx: usize) -> ChildName { + fn child_name(&self, _instance: &CastFnOptions, child_idx: usize) -> ChildName { match child_idx { 0 => ChildName::from("input"), _ => unreachable!("Invalid child index {} for Cast expression", child_idx), } } - fn fmt_sql(&self, dtype: &DType, expr: &Expression, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt_sql( + &self, + instance: &CastFnOptions, + expr: &Expression, + f: &mut Formatter<'_>, + ) -> std::fmt::Result { write!(f, "cast(")?; expr.children()[0].fmt_sql(f)?; - write!(f, " as {}", dtype)?; + write!(f, " as {}", instance)?; write!(f, ")") } - fn return_dtype(&self, dtype: &DType, _arg_dtypes: &[DType]) -> VortexResult { - Ok(dtype.clone()) + fn return_dtype(&self, instance: &CastFnOptions, _arg_dtypes: &[DType]) -> VortexResult { + Ok(instance.target.clone()) } fn execute( &self, - target_dtype: &DType, + instance: &CastFnOptions, args: &dyn ExecutionArgs, ctx: &mut ExecutionCtx, ) -> VortexResult { let input = args.get(0)?; let Some(columnar) = input.as_opt::() else { - return input.execute::(ctx)?.cast(target_dtype.clone()); + return input + .execute::(ctx)? + .cast_opts(instance.target.clone(), instance.options); }; match columnar { ColumnarView::Canonical(canonical) => { - match cast_canonical(canonical, target_dtype, ctx)? { + match cast_canonical(canonical, &instance.target, &instance.options, ctx)? { Some(result) => Ok(result), None => vortex_bail!( "No CastKernel to cast canonical array {} from {} to {}", canonical.to_array_ref().encoding_id(), canonical.to_array_ref().dtype(), - target_dtype, + instance.target, + ), + } + } + ColumnarView::Constant(constant) => { + match cast_constant(constant, &instance.target, &instance.options)? { + Some(result) => Ok(result), + None => vortex_bail!( + "No CastReduce to cast constant array from {} to {}", + constant.dtype(), + instance.target, ), } } - ColumnarView::Constant(constant) => match cast_constant(constant, target_dtype)? { - Some(result) => Ok(result), - None => vortex_bail!( - "No CastReduce to cast constant array from {} to {}", - constant.dtype(), - target_dtype, - ), - }, } } fn reduce( &self, - target_dtype: &DType, + instance: &CastFnOptions, node: &dyn ReduceNode, _ctx: &dyn ReduceCtx, ) -> VortexResult> { // Collapse node if child is already the target type let child = node.child(0); - if &child.node_dtype()? == target_dtype { + if child.node_dtype()? == instance.target { return Ok(Some(child)); } Ok(None) @@ -152,7 +292,7 @@ impl ScalarFnVTable for Cast { fn stat_expression( &self, - dtype: &DType, + instance: &CastFnOptions, expr: &Expression, stat: Stat, catalog: &dyn StatsCatalog, @@ -168,7 +308,7 @@ impl ScalarFnVTable for Cast { // We cast min/max to the new type expr.child(0) .stat_expression(stat, catalog) - .map(|x| cast(x, dtype.clone())) + .map(|x| cast(x, instance.target.clone())) } Stat::NullCount => { // if !expr.data().is_nullable() { @@ -183,8 +323,12 @@ impl ScalarFnVTable for Cast { } } - fn validity(&self, dtype: &DType, expression: &Expression) -> VortexResult> { - Ok(Some(if dtype.is_nullable() { + fn validity( + &self, + instance: &CastFnOptions, + expression: &Expression, + ) -> VortexResult> { + Ok(Some(if instance.target.is_nullable() { expression.child(0).validity()? } else { lit(true) @@ -192,7 +336,7 @@ impl ScalarFnVTable for Cast { } // This might apply a nullability - fn is_null_sensitive(&self, _instance: &DType) -> bool { + fn is_null_sensitive(&self, _instance: &CastFnOptions) -> bool { true } } @@ -202,18 +346,19 @@ impl ScalarFnVTable for Cast { fn cast_canonical( canonical: CanonicalView<'_>, dtype: &DType, + options: &CastOptions, ctx: &mut ExecutionCtx, ) -> VortexResult> { match canonical { - CanonicalView::Null(a) => ::cast(a, dtype), - CanonicalView::Bool(a) => ::cast(a, dtype), - CanonicalView::Primitive(a) => ::cast(a, dtype, ctx), - CanonicalView::Decimal(a) => ::cast(a, dtype, ctx), - CanonicalView::VarBinView(a) => ::cast(a, dtype), - CanonicalView::List(a) => ::cast(a, dtype), - CanonicalView::FixedSizeList(a) => ::cast(a, dtype), - CanonicalView::Struct(a) => ::cast(a, dtype, ctx), - CanonicalView::Extension(a) => ::cast(a, dtype), + CanonicalView::Null(a) => ::cast(a, dtype, options), + CanonicalView::Bool(a) => ::cast(a, dtype, options), + CanonicalView::Primitive(a) => ::cast(a, dtype, options, ctx), + CanonicalView::Decimal(a) => ::cast(a, dtype, options, ctx), + CanonicalView::VarBinView(a) => ::cast(a, dtype, options), + CanonicalView::List(a) => ::cast(a, dtype, options), + CanonicalView::FixedSizeList(a) => ::cast(a, dtype, options), + CanonicalView::Struct(a) => ::cast(a, dtype, options, ctx), + CanonicalView::Extension(a) => ::cast(a, dtype, options), CanonicalView::Variant(_) => { vortex_bail!("Variant arrays don't support casting") } @@ -221,8 +366,12 @@ fn cast_canonical( } /// Cast a constant array by dispatching to its [`CastReduce`] implementation. -fn cast_constant(array: ArrayView, dtype: &DType) -> VortexResult> { - ::cast(array, dtype) +fn cast_constant( + array: ArrayView, + dtype: &DType, + options: &CastOptions, +) -> VortexResult> { + ::cast(array, dtype, options) } #[cfg(test)] diff --git a/vortex-datafusion/src/convert/exprs.rs b/vortex-datafusion/src/convert/exprs.rs index 6a9ac0fdc52..288885a459e 100644 --- a/vortex-datafusion/src/convert/exprs.rs +++ b/vortex-datafusion/src/convert/exprs.rs @@ -235,6 +235,9 @@ impl ExpressionConvertor for DefaultExpressionConvertor { let target_dtype = DType::from_arrow((target.data_type(), target.is_nullable().into())); let child = self.convert(cast_col_expr.expr().as_ref())?; + // Column casts come from schema adaptation (e.g., reading a file with a different + // physical schema): the default by-name match tolerates reordering and added + // nullable fields. return Ok(cast(child, target_dtype)); } diff --git a/vortex-proto/proto/expr.proto b/vortex-proto/proto/expr.proto index 73ba7209a15..c48cf7f9175 100644 --- a/vortex-proto/proto/expr.proto +++ b/vortex-proto/proto/expr.proto @@ -72,8 +72,15 @@ message LikeOpts { bool case_insensitive = 2; } +enum CastMode { + // BY_NAME is the default cast mode; positional cast requires an explicit option. + BY_NAME = 0; + BY_POSITION = 1; +} + message CastOpts { vortex.dtype.DType target = 1; + CastMode mode = 2; } message FieldNames { diff --git a/vortex-proto/public-api.lock b/vortex-proto/public-api.lock index 045b53d17eb..b3f41ffa40b 100644 --- a/vortex-proto/public-api.lock +++ b/vortex-proto/public-api.lock @@ -768,6 +768,68 @@ pub fn vortex_proto::expr::select_opts::Opts::hash<__H: core::hash::Hasher>(&sel impl core::marker::StructuralPartialEq for vortex_proto::expr::select_opts::Opts +#[repr(i32)] pub enum vortex_proto::expr::CastMode + +pub vortex_proto::expr::CastMode::ByName = 0 + +pub vortex_proto::expr::CastMode::ByPosition = 1 + +impl vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::as_str_name(&self) -> &'static str + +pub fn vortex_proto::expr::CastMode::from_str_name(value: &str) -> core::option::Option + +impl vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::from_i32(value: i32) -> core::option::Option + +pub fn vortex_proto::expr::CastMode::is_valid(value: i32) -> bool + +impl core::clone::Clone for vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::clone(&self) -> vortex_proto::expr::CastMode + +impl core::cmp::Eq for vortex_proto::expr::CastMode + +impl core::cmp::Ord for vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::cmp(&self, other: &vortex_proto::expr::CastMode) -> core::cmp::Ordering + +impl core::cmp::PartialEq for vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::eq(&self, other: &vortex_proto::expr::CastMode) -> bool + +impl core::cmp::PartialOrd for vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::partial_cmp(&self, other: &vortex_proto::expr::CastMode) -> core::option::Option + +impl core::convert::From for i32 + +pub fn i32::from(value: vortex_proto::expr::CastMode) -> i32 + +impl core::convert::TryFrom for vortex_proto::expr::CastMode + +pub type vortex_proto::expr::CastMode::Error = prost::error::UnknownEnumValue + +pub fn vortex_proto::expr::CastMode::try_from(value: i32) -> core::result::Result + +impl core::default::Default for vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::default() -> vortex_proto::expr::CastMode + +impl core::fmt::Debug for vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::hash::Hash for vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastMode::hash<__H: core::hash::Hasher>(&self, state: &mut __H) + +impl core::marker::Copy for vortex_proto::expr::CastMode + +impl core::marker::StructuralPartialEq for vortex_proto::expr::CastMode + pub struct vortex_proto::expr::AggregateFn pub vortex_proto::expr::AggregateFn::id: alloc::string::String @@ -926,8 +988,16 @@ pub fn vortex_proto::expr::CaseWhenOpts::encoded_len(&self) -> usize pub struct vortex_proto::expr::CastOpts +pub vortex_proto::expr::CastOpts::mode: i32 + pub vortex_proto::expr::CastOpts::target: core::option::Option +impl vortex_proto::expr::CastOpts + +pub fn vortex_proto::expr::CastOpts::mode(&self) -> vortex_proto::expr::CastMode + +pub fn vortex_proto::expr::CastOpts::set_mode(&mut self, value: vortex_proto::expr::CastMode) + impl core::clone::Clone for vortex_proto::expr::CastOpts pub fn vortex_proto::expr::CastOpts::clone(&self) -> vortex_proto::expr::CastOpts diff --git a/vortex-proto/src/generated/vortex.expr.rs b/vortex-proto/src/generated/vortex.expr.rs index 9c7ddb1d90c..294d6f6cb7d 100644 --- a/vortex-proto/src/generated/vortex.expr.rs +++ b/vortex-proto/src/generated/vortex.expr.rs @@ -132,6 +132,8 @@ pub struct LikeOpts { pub struct CastOpts { #[prost(message, optional, tag = "1")] pub target: ::core::option::Option, + #[prost(enumeration = "CastMode", tag = "2")] + pub mode: i32, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct FieldNames { @@ -163,3 +165,30 @@ pub struct CaseWhenOpts { #[prost(uint32, tag = "1")] pub num_children: u32, } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum CastMode { + /// BY_NAME is the default cast mode; positional cast requires an explicit option. + ByName = 0, + ByPosition = 1, +} +impl CastMode { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::ByName => "BY_NAME", + Self::ByPosition => "BY_POSITION", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "BY_NAME" => Some(Self::ByName), + "BY_POSITION" => Some(Self::ByPosition), + _ => None, + } + } +}