Skip to content

Commit 528b760

Browse files
authored
fix: RunEnd encoding doesn't skip first value when encoding nullable arrays (#1674)
1 parent 2788c6c commit 528b760

File tree

1 file changed

+31
-14
lines changed

1 file changed

+31
-14
lines changed

encodings/runend/src/compress.rs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,18 @@ fn runend_encode_primitive<T: NativePType>(elements: &[T]) -> (Vec<u64>, Vec<T>)
5656
}
5757

5858
// Run-end encode the values
59-
let mut last = elements[0];
59+
let mut prev = elements[0];
6060
let mut end = 1;
6161
for &e in elements.iter().skip(1) {
62-
if e != last {
62+
if e != prev {
6363
ends.push(end);
64-
values.push(last);
64+
values.push(prev);
6565
}
66-
last = e;
66+
prev = e;
6767
end += 1;
6868
}
6969
ends.push(end);
70-
values.push(last);
70+
values.push(prev);
7171

7272
(ends, values)
7373
}
@@ -91,40 +91,40 @@ fn runend_encode_nullable_primitive<T: NativePType>(
9191
}
9292

9393
// Run-end encode the values
94-
let mut last = element_validity.value(0).then(|| elements[0]);
94+
let mut prev = element_validity.value(0).then(|| elements[0]);
9595
let mut end = 1;
9696
for e in elements
9797
.iter()
9898
.zip(element_validity.iter())
9999
.map(|(&e, is_valid)| is_valid.then_some(e))
100100
.skip(1)
101101
{
102-
if e != last {
102+
if e != prev {
103103
ends.push(end);
104-
match e {
104+
match prev {
105105
None => {
106106
validity.append(false);
107107
values.push(T::default());
108108
}
109-
Some(e) => {
109+
Some(p) => {
110110
validity.append(true);
111-
values.push(e);
111+
values.push(p);
112112
}
113113
}
114114
}
115-
last = e;
115+
prev = e;
116116
end += 1;
117117
}
118118
ends.push(end);
119119

120-
match last {
120+
match prev {
121121
None => {
122122
validity.append(false);
123123
values.push(T::default());
124124
}
125-
Some(e) => {
125+
Some(p) => {
126126
validity.append(true);
127-
values.push(e);
127+
values.push(p);
128128
}
129129
}
130130

@@ -272,7 +272,9 @@ pub fn runend_decode_typed_bool(
272272

273273
#[cfg(test)]
274274
mod test {
275+
use arrow_buffer::BooleanBuffer;
275276
use vortex_array::array::PrimitiveArray;
277+
use vortex_array::validity::Validity;
276278
use vortex_array::IntoArrayVariant;
277279

278280
use crate::compress::{runend_decode_primitive, runend_encode};
@@ -287,6 +289,21 @@ mod test {
287289
assert_eq!(values.maybe_null_slice::<i32>(), vec![1, 2, 3]);
288290
}
289291

292+
#[test]
293+
fn encode_nullable() {
294+
let arr = PrimitiveArray::from_vec(
295+
vec![1i32, 1, 2, 2, 2, 3, 3, 3, 3, 3],
296+
Validity::from(BooleanBuffer::from(vec![
297+
true, true, false, false, true, true, true, true, false, false,
298+
])),
299+
);
300+
let (ends, values) = runend_encode(&arr).unwrap();
301+
let values = values.into_primitive().unwrap();
302+
303+
assert_eq!(ends.maybe_null_slice::<u64>(), vec![2, 4, 5, 8, 10]);
304+
assert_eq!(values.maybe_null_slice::<i32>(), vec![1, 0, 2, 3, 0]);
305+
}
306+
290307
#[test]
291308
fn decode() {
292309
let ends = PrimitiveArray::from(vec![2, 5, 10]);

0 commit comments

Comments
 (0)