• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vortex-data / vortex / 16935267080

13 Aug 2025 11:00AM UTC coverage: 24.312% (-63.3%) from 87.658%
16935267080

Pull #4226

github

web-flow
Merge 81b48c7fb into baa6ea202
Pull Request #4226: Support converting TimestampTZ to and from duckdb

0 of 2 new or added lines in 1 file covered. (0.0%)

20666 existing lines in 469 files now uncovered.

8726 of 35892 relevant lines covered (24.31%)

147.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

11.5
/vortex-array/src/builders/mod.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
//! Builders for Vortex arrays.
5
//!
6
//! Every logical type in Vortex has a canonical (uncompressed) in-memory encoding. This module
7
//! provides pre-allocated builders to construct new canonical arrays.
8
//!
9
//! ## Example:
10
//!
11
//! ```
12
//! use vortex_array::builders::{builder_with_capacity, ArrayBuilderExt};
13
//! use vortex_dtype::{DType, Nullability};
14
//!
15
//! // Create a new builder for string data.
16
//! let mut builder = builder_with_capacity(&DType::Utf8(Nullability::NonNullable), 4);
17
//!
18
//! builder.append_scalar(&"a".into()).unwrap();
19
//! builder.append_scalar(&"b".into()).unwrap();
20
//! builder.append_scalar(&"c".into()).unwrap();
21
//! builder.append_scalar(&"d".into()).unwrap();
22
//!
23
//! let strings = builder.finish();
24
//!
25
//! assert_eq!(strings.scalar_at(0).unwrap(), "a".into());
26
//! assert_eq!(strings.scalar_at(1).unwrap(), "b".into());
27
//! assert_eq!(strings.scalar_at(2).unwrap(), "c".into());
28
//! assert_eq!(strings.scalar_at(3).unwrap(), "d".into());
29
//! ```
30

31
mod bool;
32
mod decimal;
33
mod extension;
34
mod lazy_validity_builder;
35
mod list;
36
mod null;
37
mod primitive;
38
mod struct_;
39
mod varbinview;
40

41
use std::any::Any;
42

43
pub use bool::*;
44
pub use decimal::*;
45
pub use extension::*;
46
pub use list::*;
47
pub use null::*;
48
pub use primitive::*;
49
pub use struct_::*;
50
pub use varbinview::*;
51
use vortex_dtype::{DType, match_each_native_ptype};
52
use vortex_error::{VortexResult, vortex_bail, vortex_err};
53
use vortex_mask::Mask;
54
use vortex_scalar::{
55
    BinaryScalar, BoolScalar, DecimalValue, ExtScalar, ListScalar, PrimitiveScalar, Scalar,
56
    ScalarValue, StructScalar, Utf8Scalar, match_each_decimal_value, match_each_decimal_value_type,
57
};
58

59
use crate::arrays::smallest_storage_type;
60
use crate::{Array, ArrayRef};
61

62
pub trait ArrayBuilder: Send {
63
    fn as_any(&self) -> &dyn Any;
64

65
    fn as_any_mut(&mut self) -> &mut dyn Any;
66

67
    fn dtype(&self) -> &DType;
68

69
    fn len(&self) -> usize;
70

71
    fn is_empty(&self) -> bool {
×
72
        self.len() == 0
×
73
    }
×
74

75
    /// Append a "zero" value to the array.
UNCOV
76
    fn append_zero(&mut self) {
×
UNCOV
77
        self.append_zeros(1)
×
UNCOV
78
    }
×
79

80
    /// Appends n "zero" values to the array.
81
    fn append_zeros(&mut self, n: usize);
82

83
    /// Append a "null" value to the array.
UNCOV
84
    fn append_null(&mut self) {
×
UNCOV
85
        self.append_nulls(1)
×
UNCOV
86
    }
×
87

88
    /// Appends n "null" values to the array.
89
    fn append_nulls(&mut self, n: usize);
90

91
    /// Extends the array with the provided array, canonicalizing if necessary.
92
    fn extend_from_array(&mut self, array: &dyn Array) -> VortexResult<()>;
93

94
    /// Ensure that the builder can hold at least `capacity` number of items
95
    fn ensure_capacity(&mut self, capacity: usize);
96

97
    /// Override builders validity with the one provided
98
    fn set_validity(&mut self, validity: Mask);
99

100
    /// Constructs an Array from the builder components.
101
    ///
102
    /// # Panics
103
    ///
104
    /// This function may panic if the builder's methods are called with invalid arguments. If only
105
    /// the methods on this interface are used, the builder should not panic. However, specific
106
    /// builders have interfaces that may be misused. For example, if the number of values in a
107
    /// [PrimitiveBuilder]'s [vortex_buffer::BufferMut] does not match the number of validity bits,
108
    /// the PrimitiveBuilder's [Self::finish] will panic.
109
    fn finish(&mut self) -> ArrayRef;
110
}
111

112
/// Construct a new canonical builder for the given [`DType`].
113
///
114
///
115
/// # Example
116
///
117
/// ```
118
/// use vortex_array::builders::{builder_with_capacity, ArrayBuilderExt};
119
/// use vortex_dtype::{DType, Nullability};
120
///
121
/// // Create a new builder for string data.
122
/// let mut builder = builder_with_capacity(&DType::Utf8(Nullability::NonNullable), 4);
123
///
124
/// builder.append_scalar(&"a".into()).unwrap();
125
/// builder.append_scalar(&"b".into()).unwrap();
126
/// builder.append_scalar(&"c".into()).unwrap();
127
/// builder.append_scalar(&"d".into()).unwrap();
128
///
129
/// let strings = builder.finish();
130
///
131
/// assert_eq!(strings.scalar_at(0).unwrap(), "a".into());
132
/// assert_eq!(strings.scalar_at(1).unwrap(), "b".into());
133
/// assert_eq!(strings.scalar_at(2).unwrap(), "c".into());
134
/// assert_eq!(strings.scalar_at(3).unwrap(), "d".into());
135
/// ```
136
pub fn builder_with_capacity(dtype: &DType, capacity: usize) -> Box<dyn ArrayBuilder> {
56✔
137
    match dtype {
56✔
UNCOV
138
        DType::Null => Box::new(NullBuilder::new()),
×
UNCOV
139
        DType::Bool(n) => Box::new(BoolBuilder::with_capacity(*n, capacity)),
×
140
        DType::Primitive(ptype, n) => {
56✔
141
            match_each_native_ptype!(ptype, |P| {
56✔
UNCOV
142
                Box::new(PrimitiveBuilder::<P>::with_capacity(*n, capacity))
×
143
            })
144
        }
UNCOV
145
        DType::Decimal(decimal_type, n) => {
×
UNCOV
146
            match_each_decimal_value_type!(smallest_storage_type(decimal_type), |D| {
×
UNCOV
147
                Box::new(DecimalBuilder::with_capacity::<D>(
×
UNCOV
148
                    capacity,
×
UNCOV
149
                    *decimal_type,
×
UNCOV
150
                    *n,
×
UNCOV
151
                ))
×
152
            })
153
        }
UNCOV
154
        DType::Utf8(n) => Box::new(VarBinViewBuilder::with_capacity(DType::Utf8(*n), capacity)),
×
UNCOV
155
        DType::Binary(n) => Box::new(VarBinViewBuilder::with_capacity(
×
UNCOV
156
            DType::Binary(*n),
×
UNCOV
157
            capacity,
×
UNCOV
158
        )),
×
UNCOV
159
        DType::Struct(struct_dtype, n) => Box::new(StructBuilder::with_capacity(
×
UNCOV
160
            struct_dtype.clone(),
×
UNCOV
161
            *n,
×
UNCOV
162
            capacity,
×
UNCOV
163
        )),
×
UNCOV
164
        DType::List(dtype, n) => Box::new(ListBuilder::<u64>::with_capacity(
×
UNCOV
165
            dtype.clone(),
×
UNCOV
166
            *n,
×
UNCOV
167
            capacity,
×
UNCOV
168
        )),
×
UNCOV
169
        DType::Extension(ext_dtype) => {
×
UNCOV
170
            Box::new(ExtensionBuilder::with_capacity(ext_dtype.clone(), capacity))
×
171
        }
172
    }
173
}
56✔
174

175
pub trait ArrayBuilderExt: ArrayBuilder {
176
    /// A generic function to append a scalar value to the builder.
177
    fn append_scalar_value(&mut self, value: ScalarValue) -> VortexResult<()> {
×
178
        if value.is_null() {
×
179
            self.append_null();
×
180
            Ok(())
×
181
        } else {
182
            self.append_scalar(&Scalar::new(self.dtype().clone(), value))
×
183
        }
184
    }
×
185

186
    /// A generic function to append a scalar to the builder.
187
    fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
72✔
188
        if scalar.dtype() != self.dtype() {
72✔
189
            vortex_bail!(
×
190
                "Builder has dtype {:?}, scalar has {:?}",
×
191
                self.dtype(),
×
192
                scalar.dtype()
×
193
            )
194
        }
72✔
195
        match scalar.dtype() {
72✔
196
            DType::Null => self
×
197
                .as_any_mut()
×
198
                .downcast_mut::<NullBuilder>()
×
199
                .ok_or_else(|| vortex_err!("Cannot append null scalar to non-null builder"))?
×
200
                .append_null(),
×
UNCOV
201
            DType::Bool(_) => self
×
UNCOV
202
                .as_any_mut()
×
UNCOV
203
                .downcast_mut::<BoolBuilder>()
×
UNCOV
204
                .ok_or_else(|| vortex_err!("Cannot append bool scalar to non-bool builder"))?
×
UNCOV
205
                .append_option(BoolScalar::try_from(scalar)?.value()),
×
206
            DType::Primitive(ptype, ..) => {
72✔
207
                match_each_native_ptype!(ptype, |P| {
72✔
UNCOV
208
                    self.as_any_mut()
×
UNCOV
209
                        .downcast_mut::<PrimitiveBuilder<P>>()
×
UNCOV
210
                        .ok_or_else(|| {
×
211
                            vortex_err!("Cannot append primitive scalar to non-primitive builder")
×
212
                        })?
×
UNCOV
213
                        .append_option(PrimitiveScalar::try_from(scalar)?.typed_value::<P>())
×
214
                })
215
            }
216
            DType::Decimal(..) => {
UNCOV
217
                let builder = self
×
UNCOV
218
                    .as_any_mut()
×
UNCOV
219
                    .downcast_mut::<DecimalBuilder>()
×
UNCOV
220
                    .ok_or_else(|| {
×
221
                        vortex_err!("Cannot append decimal scalar to non-decimal builder")
×
222
                    })?;
×
UNCOV
223
                match scalar.as_decimal().decimal_value() {
×
224
                    None => builder.append_null(),
×
UNCOV
225
                    Some(v) => match_each_decimal_value!(v, |dec_val| {
×
UNCOV
226
                        builder.append_value(dec_val);
×
UNCOV
227
                    }),
×
228
                }
229
            }
UNCOV
230
            DType::Utf8(_) => self
×
UNCOV
231
                .as_any_mut()
×
UNCOV
232
                .downcast_mut::<VarBinViewBuilder>()
×
UNCOV
233
                .ok_or_else(|| vortex_err!("Cannot append utf8 scalar to non-utf8 builder"))?
×
UNCOV
234
                .append_option(Utf8Scalar::try_from(scalar)?.value()),
×
UNCOV
235
            DType::Binary(_) => self
×
UNCOV
236
                .as_any_mut()
×
UNCOV
237
                .downcast_mut::<VarBinViewBuilder>()
×
UNCOV
238
                .ok_or_else(|| vortex_err!("Cannot append binary scalar to non-binary builder"))?
×
UNCOV
239
                .append_option(BinaryScalar::try_from(scalar)?.value()),
×
240
            DType::Struct(..) => self
×
241
                .as_any_mut()
×
242
                .downcast_mut::<StructBuilder>()
×
243
                .ok_or_else(|| vortex_err!("Cannot append struct scalar to non-struct builder"))?
×
244
                .append_value(StructScalar::try_from(scalar)?)?,
×
245
            DType::List(..) => self
×
246
                .as_any_mut()
×
247
                .downcast_mut::<ListBuilder<u64>>()
×
248
                .ok_or_else(|| vortex_err!("Cannot append list scalar to non-list builder"))?
×
249
                .append_value(ListScalar::try_from(scalar)?)?,
×
UNCOV
250
            DType::Extension(..) => self
×
UNCOV
251
                .as_any_mut()
×
UNCOV
252
                .downcast_mut::<ExtensionBuilder>()
×
UNCOV
253
                .ok_or_else(|| {
×
254
                    vortex_err!("Cannot append extension scalar to non-extension builder")
×
255
                })?
×
UNCOV
256
                .append_value(ExtScalar::try_from(scalar)?)?,
×
257
        }
258
        Ok(())
72✔
259
    }
72✔
260
}
261

262
impl<T: ?Sized + ArrayBuilder> ArrayBuilderExt for T {}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc