Skip to content

Commit 50c3d57

Browse files
authored
Chore: Validate Scalar::new for null and clean up DecimalScalar (#4435)
Progress towards #4378 ~~I don't think that it makes a lot of sense to add `new_unchecked` given that the only check we really need is `!dtype.is_nullable()` (which is cheap), and by making the fields private we can guarantee this invariant.~~ Edit: In the future the `Scalar::new` should validate that the dtype matches the value that is passed in. Also cleans up the `decimal` module in `vortex-scalar`. --------- Signed-off-by: Connor Tsui <[email protected]>
1 parent e54da40 commit 50c3d57

File tree

14 files changed

+570
-551
lines changed

14 files changed

+570
-551
lines changed

vortex-array/src/builders/list.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ impl<O: OffsetPType> ArrayBuilder for ListBuilder<O> {
123123

124124
fn append_zeros(&mut self, n: usize) {
125125
let count = self.value_builder.len();
126+
// TODO(connor): this is incorrect, as it creates lists of size 1 instead of 0.
126127
self.value_builder.append_zeros(n);
127128
for i in 0..n {
128129
self.append_index(

vortex-scalar/src/binary.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ impl<'a> BinaryScalar<'a> {
168168
impl Scalar {
169169
/// Creates a new binary scalar from a byte buffer.
170170
pub fn binary(buffer: impl Into<ByteBuffer>, nullability: Nullability) -> Self {
171-
Self {
172-
dtype: DType::Binary(nullability),
173-
value: ScalarValue(InnerScalarValue::Buffer(Arc::new(buffer.into()))),
174-
}
171+
Self::new(
172+
DType::Binary(nullability),
173+
ScalarValue(InnerScalarValue::Buffer(Arc::new(buffer.into()))),
174+
)
175175
}
176176
}
177177

@@ -184,7 +184,7 @@ impl<'a> TryFrom<&'a Scalar> for BinaryScalar<'a> {
184184
}
185185
Ok(Self {
186186
dtype: value.dtype(),
187-
value: value.value.as_buffer()?,
187+
value: value.value().as_buffer()?,
188188
})
189189
}
190190
}
@@ -238,19 +238,16 @@ impl From<&[u8]> for Scalar {
238238

239239
impl From<ByteBuffer> for Scalar {
240240
fn from(value: ByteBuffer) -> Self {
241-
Self {
242-
dtype: DType::Binary(Nullability::NonNullable),
243-
value: value.into(),
244-
}
241+
Self::new(DType::Binary(Nullability::NonNullable), value.into())
245242
}
246243
}
247244

248245
impl From<Arc<ByteBuffer>> for Scalar {
249246
fn from(value: Arc<ByteBuffer>) -> Self {
250-
Self {
251-
dtype: DType::Binary(Nullability::NonNullable),
252-
value: ScalarValue(InnerScalarValue::Buffer(value)),
253-
}
247+
Self::new(
248+
DType::Binary(Nullability::NonNullable),
249+
ScalarValue(InnerScalarValue::Buffer(value)),
250+
)
254251
}
255252
}
256253

vortex-scalar/src/bool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl<'a> TryFrom<&'a Scalar> for BoolScalar<'a> {
111111
}
112112
Ok(Self {
113113
dtype: value.dtype(),
114-
value: value.value.as_bool()?,
114+
value: value.value().as_bool()?,
115115
})
116116
}
117117
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
/// Implements `NativeDecimalType` for the given type.
5+
macro_rules! impl_native_decimal_type {
6+
($T:ty, $variant:ident) => {
7+
impl NativeDecimalType for $T {
8+
const VALUES_TYPE: DecimalValueType = DecimalValueType::$variant;
9+
10+
fn maybe_from(decimal_type: DecimalValue) -> Option<Self> {
11+
if let DecimalValue::$variant(v) = decimal_type {
12+
Some(v)
13+
} else {
14+
None
15+
}
16+
}
17+
}
18+
};
19+
}
20+
pub(crate) use impl_native_decimal_type;
21+
22+
/// Implements `TryFrom<DecimalScalar>` for the given type.
23+
macro_rules! decimal_scalar_unpack {
24+
($T:ident, $arm:ident) => {
25+
impl TryFrom<DecimalScalar<'_>> for Option<$T> {
26+
type Error = VortexError;
27+
28+
fn try_from(value: DecimalScalar) -> Result<Self, Self::Error> {
29+
Ok(match value.value {
30+
None => None,
31+
Some(DecimalValue::$arm(v)) => Some(v),
32+
v => vortex_error::vortex_bail!(
33+
"Cannot extract decimal {:?} as {}",
34+
v,
35+
stringify!($T)
36+
),
37+
})
38+
}
39+
}
40+
41+
impl TryFrom<DecimalScalar<'_>> for $T {
42+
type Error = VortexError;
43+
44+
fn try_from(value: DecimalScalar) -> Result<Self, Self::Error> {
45+
match value.value {
46+
None => vortex_error::vortex_bail!("Cannot extract value from null decimal"),
47+
Some(DecimalValue::$arm(v)) => Ok(v),
48+
v => vortex_error::vortex_bail!(
49+
"Cannot extract decimal {:?} as {}",
50+
v,
51+
stringify!($T)
52+
),
53+
}
54+
}
55+
}
56+
};
57+
}
58+
pub(crate) use decimal_scalar_unpack;
59+
60+
/// Implements `Into<DecimalValue>` for the given type.
61+
macro_rules! decimal_scalar_pack {
62+
($from:ident, $to:ident, $arm:ident) => {
63+
impl From<$from> for DecimalValue {
64+
fn from(value: $from) -> Self {
65+
DecimalValue::$arm(value as $to)
66+
}
67+
}
68+
};
69+
}
70+
pub(crate) use decimal_scalar_pack;
71+
72+
/// Matches over each decimal value variant, binding the inner value to a variable.
73+
///
74+
/// # Example
75+
///
76+
/// ```ignore
77+
/// match_each_decimal_value!(value, |v| {
78+
/// println!("Value: {}", v);
79+
/// });
80+
/// ```
81+
#[macro_export] // Used in `vortex-array`.
82+
macro_rules! match_each_decimal_value {
83+
($self:expr, | $value:ident | $body:block) => {{
84+
match $self {
85+
DecimalValue::I8(v) => {
86+
let $value = v;
87+
$body
88+
}
89+
DecimalValue::I16(v) => {
90+
let $value = v;
91+
$body
92+
}
93+
DecimalValue::I32(v) => {
94+
let $value = v;
95+
$body
96+
}
97+
DecimalValue::I64(v) => {
98+
let $value = v;
99+
$body
100+
}
101+
DecimalValue::I128(v) => {
102+
let $value = v;
103+
$body
104+
}
105+
DecimalValue::I256(v) => {
106+
let $value = v;
107+
$body
108+
}
109+
}
110+
}};
111+
}
112+
113+
/// Macro to match over each decimal value type, binding the corresponding native type (from
114+
/// `DecimalValueType`)
115+
#[macro_export] // Used in `vortex-array`.
116+
macro_rules! match_each_decimal_value_type {
117+
($self:expr, | $enc:ident | $body:block) => {{
118+
use $crate::{DecimalValueType, i256};
119+
match $self {
120+
DecimalValueType::I8 => {
121+
type $enc = i8;
122+
$body
123+
}
124+
DecimalValueType::I16 => {
125+
type $enc = i16;
126+
$body
127+
}
128+
DecimalValueType::I32 => {
129+
type $enc = i32;
130+
$body
131+
}
132+
DecimalValueType::I64 => {
133+
type $enc = i64;
134+
$body
135+
}
136+
DecimalValueType::I128 => {
137+
type $enc = i128;
138+
$body
139+
}
140+
DecimalValueType::I256 => {
141+
type $enc = i256;
142+
$body
143+
}
144+
ty => unreachable!("unknown decimal value type {:?}", ty),
145+
}
146+
}};
147+
}

0 commit comments

Comments
 (0)