Skip to content

Commit d4bab58

Browse files
authored
Feature: Struct Vectors (#5094)
Tracking Issue: #5028 Adds `StructVector` and `StructVectorMut`. Note: It would be really nice to have something like serde values that we can iterate and take as an iterator to construct these struct vectors, otherwise we are left with what I currently have on this PR, which imo is very unwieldy. This can come in a later PR though. The second commit fixes some errors and also removes all of the `new` functions for vectors (as per an offline discussion with @gatesn). --------- Signed-off-by: Connor Tsui <[email protected]>
1 parent 1c01fae commit d4bab58

File tree

18 files changed

+1111
-66
lines changed

18 files changed

+1111
-66
lines changed

vortex-array/src/arrays/bool/vtable/operator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl OperatorVTable<BoolVTable> for BoolVTable {
2727
// Note that validity already has the mask applied so we only need to apply it to bits.
2828
let bits = bits.filter(&mask);
2929

30-
Ok(BoolVector::new(bits, validity).into())
30+
Ok(BoolVector::try_new(bits, validity)?.into())
3131
}))
3232
}
3333
}

vortex-array/src/arrays/primitive/vtable/operator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl OperatorVTable<PrimitiveVTable> for PrimitiveVTable {
3030
// the elements.
3131
let elements = elements.filter(&mask);
3232

33-
Ok(PVector::new(elements, validity).into())
33+
Ok(PVector::try_new(elements, validity)?.into())
3434
}))
3535
})
3636
}

vortex-compute/src/filter/bool.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ use crate::filter::Filter;
88

99
impl Filter for BoolVector {
1010
fn filter(&self, mask: &Mask) -> Self {
11-
Self::new(self.bits().filter(mask), self.validity().filter(mask))
11+
let filtered_bits = self.bits().filter(mask);
12+
let filtered_validity = self.validity().filter(mask);
13+
14+
// SAFETY: We filter the bits and validity with the same mask, and since they came from an
15+
// existing and valid `BoolVector`, we know that the filtered output must have the same
16+
// length.
17+
unsafe { Self::new_unchecked(filtered_bits, filtered_validity) }
1218
}
1319
}

vortex-vector/src/bool/iter.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ impl FromIterator<bool> for BoolVectorMut {
8585
///
8686
/// It consumes the mutable vector and iterates over the elements, yielding `None` for null values
8787
/// and `Some(value)` for valid values.
88+
#[derive(Debug)]
8889
pub struct BoolVectorMutIterator {
8990
/// The vector being iterated over.
9091
vector: BoolVectorMut,

vortex-vector/src/bool/vector.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ impl BoolVector {
3030
///
3131
/// Panics if the length of the validity mask does not match the length of the bits.
3232
pub fn new(bits: BitBuffer, validity: Mask) -> Self {
33-
Self::try_new(bits, validity)
34-
.vortex_expect("`BoolVector` validity mask must have the same length as bits")
33+
Self::try_new(bits, validity).vortex_expect("Failed to create `BoolVector`")
3534
}
3635

3736
/// Tries to create a new [`BoolVector`] from the given bits and validity mask.
@@ -53,17 +52,15 @@ impl BoolVector {
5352
/// # Safety
5453
///
5554
/// The caller must ensure that the validity mask has the same length as the bits.
56-
pub fn new_unchecked(bits: BitBuffer, validity: Mask) -> Self {
57-
debug_assert_eq!(
58-
validity.len(),
59-
bits.len(),
60-
"`BoolVector` validity mask must have the same length as bits"
61-
);
62-
63-
Self { bits, validity }
55+
pub unsafe fn new_unchecked(bits: BitBuffer, validity: Mask) -> Self {
56+
if cfg!(debug_assertions) {
57+
Self::new(bits, validity)
58+
} else {
59+
Self { bits, validity }
60+
}
6461
}
6562

66-
/// Decomposes the boolean vector into its constituent parts.
63+
/// Decomposes the boolean vector into its constituent parts (bit buffer and validity).
6764
pub fn into_parts(self) -> (BitBuffer, Mask) {
6865
(self.bits, self.validity)
6966
}

vortex-vector/src/bool/vector_mut.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ impl BoolVectorMut {
7777
///
7878
/// Panics if the length of the validity mask does not match the length of the bits.
7979
pub fn new(bits: BitBufferMut, validity: MaskMut) -> Self {
80-
Self::try_new(bits, validity)
81-
.vortex_expect("`BoolVector` validity mask must have the same length as bits")
80+
Self::try_new(bits, validity).vortex_expect("Failed to create `BoolVectorMut`")
8281
}
8382

8483
/// Tries to create a new [`BoolVectorMut`] from the given bits and validity mask.
@@ -104,13 +103,11 @@ impl BoolVectorMut {
104103
/// Ideally, they are taken from `into_parts`, mutated in a way that doesn't re-allocate, and
105104
/// then passed back to this function.
106105
pub unsafe fn new_unchecked(bits: BitBufferMut, validity: MaskMut) -> Self {
107-
debug_assert_eq!(
108-
bits.len(),
109-
validity.len(),
110-
"`BoolVector` validity mask must have the same length as bits"
111-
);
112-
113-
Self { bits, validity }
106+
if cfg!(debug_assertions) {
107+
Self::new(bits, validity)
108+
} else {
109+
Self { bits, validity }
110+
}
114111
}
115112

116113
/// Creates a new mutable boolean vector with the given `capacity`.
@@ -121,7 +118,7 @@ impl BoolVectorMut {
121118
}
122119
}
123120

124-
/// Returns the parts of the mutable vector.
121+
/// Decomposes the boolean vector into its constituent parts (bit buffer and validity).
125122
pub fn into_parts(self) -> (BitBufferMut, MaskMut) {
126123
(self.bits, self.validity)
127124
}
@@ -151,7 +148,7 @@ impl VectorMutOps for BoolVectorMut {
151148
}
152149

153150
fn append_nulls(&mut self, n: usize) {
154-
self.bits.append_n(false, n);
151+
self.bits.append_n(false, n); // Note that the value we push doesn't actually matter.
155152
self.validity.append_n(false, n);
156153
}
157154

vortex-vector/src/lib.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,22 @@
1212
#![deny(clippy::missing_safety_doc)]
1313

1414
mod bool;
15-
mod macros;
1615
mod null;
17-
mod ops;
1816
mod primitive;
19-
mod private;
20-
mod vector;
21-
mod vector_mut;
17+
mod struct_;
2218

2319
pub use bool::{BoolVector, BoolVectorMut};
2420
pub use null::{NullVector, NullVectorMut};
25-
pub use ops::{VectorMutOps, VectorOps};
2621
pub use primitive::{PVector, PVectorMut, PrimitiveVector, PrimitiveVectorMut};
22+
pub use struct_::{StructVector, StructVectorMut};
23+
24+
mod ops;
25+
mod vector;
26+
mod vector_mut;
27+
28+
pub use ops::{VectorMutOps, VectorOps};
2729
pub use vector::Vector;
2830
pub use vector_mut::VectorMut;
31+
32+
mod macros;
33+
mod private;

vortex-vector/src/macros.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ macro_rules! match_each_vector {
4848
let $vec = v;
4949
$body
5050
}
51+
$crate::Vector::Struct(v) => {
52+
let $vec = v;
53+
$body
54+
}
5155
}
5256
}};
5357
}
@@ -98,6 +102,10 @@ macro_rules! match_each_vector_mut {
98102
let $vec = v;
99103
$body
100104
}
105+
$crate::VectorMut::Struct(v) => {
106+
let $vec = v;
107+
$body
108+
}
101109
}
102110
}};
103111
}

vortex-vector/src/ops.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ pub trait VectorMutOps: private::Sealed + Into<VectorMut> {
7070
fn reserve(&mut self, additional: usize);
7171

7272
/// Extends the vector by appending elements from another vector.
73+
///
74+
/// # Panics
75+
///
76+
/// Panics if the `other` vector has the wrong type (for example, a
77+
/// [`StructVector`](crate::StructVector) might have incorrect fields).
7378
fn extend_from_vector(&mut self, other: &Self::Immutable);
7479

7580
/// Appends `n` null elements to the vector.

vortex-vector/src/primitive/generic.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ impl<T: NativePType> PVector<T> {
3434
///
3535
/// Panics if the length of the validity mask does not match the length of the elements buffer.
3636
pub fn new(elements: Buffer<T>, validity: Mask) -> Self {
37-
Self::try_new(elements, validity)
38-
.vortex_expect("`PVector` validity mask must have the same length as elements")
37+
Self::try_new(elements, validity).vortex_expect("Failed to create `PVector`")
3938
}
4039

4140
/// Tries to create a new [`PVector<T>`] from the given elements buffer and validity mask.
@@ -59,17 +58,15 @@ impl<T: NativePType> PVector<T> {
5958
/// # Safety
6059
///
6160
/// The caller must ensure that the validity mask has the same length as the elements buffer.
62-
pub fn new_unchecked(elements: Buffer<T>, validity: Mask) -> Self {
63-
debug_assert_eq!(
64-
validity.len(),
65-
elements.len(),
66-
"`PVector` validity mask must have the same length as elements"
67-
);
68-
69-
Self { elements, validity }
61+
pub unsafe fn new_unchecked(elements: Buffer<T>, validity: Mask) -> Self {
62+
if cfg!(debug_assertions) {
63+
Self::new(elements, validity)
64+
} else {
65+
Self { elements, validity }
66+
}
7067
}
7168

72-
/// Decomposes the primitive vector into its constituent parts.
69+
/// Decomposes the primitive vector into its constituent parts (buffer and validity).
7370
pub fn into_parts(self) -> (Buffer<T>, Mask) {
7471
(self.elements, self.validity)
7572
}

0 commit comments

Comments
 (0)