Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 10 additions & 51 deletions encodings/decimal-byte-parts/src/decimal_byte_parts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ use std::fmt::Display;
use std::fmt::Formatter;
use std::hash::Hasher;

use prost::Message as _;
use vortex_array::Array;
use vortex_array::ArrayParts;
use vortex_array::ArrayView;
pub(crate) mod compute;
mod limbs;
mod plugin;
mod rules;
#[cfg(test)]
pub(crate) mod testing;
Expand All @@ -22,7 +24,8 @@ pub mod _benchmarking {
pub use super::limbs::assemble_decimal;
}

use prost::Message as _;
pub use plugin::DecimalBytePartsPlugin;
pub use plugin::decimal_byte_parts_v2_id;
use vortex_array::ArrayEq;
use vortex_array::ArrayHash;
use vortex_array::ArrayId;
Expand Down Expand Up @@ -177,7 +180,9 @@ impl DecimalByteParts {
lower_parts: Vec<ArrayRef>,
decimal_dtype: DecimalDType,
) -> VortexResult<DecimalBytePartsArray> {
// Lower parts are supported in memory; the frozen serializer still rejects them.
// Building lower parts in memory is never gated — reading a file requires it. What is
// gated is the serialized form: an array carrying lower parts serializes under the
// `vortex.decimal_byte_parts_v2` format ID, which only editions that contain it may write.
let len = msp.len();
let dtype = DType::Decimal(decimal_dtype, msp.dtype().nullability());
let slots = DecimalBytePartsSlots { msp, lower_parts }.into_slots();
Expand Down Expand Up @@ -256,7 +261,7 @@ impl VTable for DecimalByteParts {
) -> VortexResult<Option<Vec<u8>>> {
vortex_ensure!(
array.lower_parts().is_empty(),
"serializing DecimalByteParts with lower parts is not supported"
"serializing DecimalByteParts with lower parts requires DecimalBytePartsPlugin"
);
Ok(Some(
DecimalBytesPartsMetadata::from_array(array)?.encode_to_vec(),
Expand Down Expand Up @@ -506,6 +511,8 @@ mod tests {
use crate::decimal_byte_parts::testing::i128_parts;
use crate::decimal_byte_parts::testing::i256_of;
use crate::decimal_byte_parts::testing::i256_parts;
use crate::decimal_byte_parts::testing::wide_i128_values;
use crate::decimal_byte_parts::testing::wide_i256_values;

#[test]
fn test_scalar_at_decimal_parts() {
Expand Down Expand Up @@ -546,47 +553,6 @@ mod tests {
);
}

/// The largest unscaled value a `Decimal(38, _)` can hold: `10^38 - 1`.
const MAX_PRECISION_38: i128 = 99_999_999_999_999_999_999_999_999_999_999_999_999;

/// The largest unscaled value a `Decimal(76, _)` can hold: `10^76 - 1`.
fn max_precision_76() -> i256 {
i256::from_i128(10).wrapping_pow(76) - i256::ONE
}

/// Values that exercise every 64-bit window of an `i128`, both signs, and the boundaries
/// where a lower part carries into the MSP.
fn wide_i128_values() -> Vec<i128> {
vec![
0,
1,
-1,
(1 << 64) - 1,
1 << 64,
-(1 << 64),
-((1 << 64) + 1),
MAX_PRECISION_38,
-MAX_PRECISION_38,
1 << 100,
]
}

/// Values that exercise every 64-bit window of an `i256`.
fn wide_i256_values() -> Vec<i256> {
vec![
i256::ZERO,
i256::ONE,
i256::ZERO - i256::ONE,
i256_of(0, u128::MAX),
i256_of(1, 0),
i256_of(-1, 0),
i256_of(-1, u128::MAX - 1),
i256_of(1 << 64, 12345),
max_precision_76(),
i256::ZERO - max_precision_76(),
]
}

#[rstest]
#[case::i128_non_nullable(i128_parts(wide_i128_values(), Validity::NonNullable))]
#[case::i256_non_nullable(i256_parts(wide_i256_values(), Validity::NonNullable))]
Expand Down Expand Up @@ -817,11 +783,4 @@ mod tests {
assert_arrays_eq!(array, canonical.into_array(), &mut ctx);
Ok(())
}
#[test]
fn test_frozen_serializer_rejects_lower_parts() -> VortexResult<()> {
let session = array_session();
let array = i128_parts(vec![1i128 << 70], Validity::NonNullable);
assert!(VTable::serialize(array.as_view(), &session).is_err());
Ok(())
}
}
Loading
Loading