hdbconnect_arrow/builders/
primitive.rs1use std::sync::Arc;
12
13use arrow_array::ArrayRef;
14use arrow_array::builder::{
15 Float32Builder, Float64Builder, Int16Builder, Int32Builder, Int64Builder, UInt8Builder,
16};
17
18use crate::Result;
19use crate::traits::builder::HanaCompatibleBuilder;
20use crate::traits::sealed::private::Sealed;
21
22macro_rules! impl_primitive_builder {
35 ($name:ident, $builder:ty, $rust_ty:ty, $hana_variant:ident) => {
36 #[derive(Debug)]
40 pub struct $name {
41 builder: $builder,
42 len: usize,
43 }
44
45 impl $name {
46 #[must_use]
48 pub fn new(capacity: usize) -> Self {
49 Self {
50 builder: <$builder>::with_capacity(capacity),
51 len: 0,
52 }
53 }
54
55 #[must_use]
57 pub fn default_capacity() -> Self {
58 Self::new(1024)
59 }
60 }
61
62 impl Sealed for $name {}
63
64 impl HanaCompatibleBuilder for $name {
65 fn append_hana_value(&mut self, value: &hdbconnect::HdbValue) -> Result<()> {
66 use hdbconnect::HdbValue;
67
68 match value {
69 HdbValue::$hana_variant(v) => {
70 let converted: $rust_ty = (*v).try_into().map_err(|e| {
71 crate::ArrowConversionError::value_conversion(
72 stringify!($name),
73 format!("cannot convert {} to {}: {}", v, stringify!($rust_ty), e),
74 )
75 })?;
76 self.builder.append_value(converted);
77 }
78 other => {
79 return Err(crate::ArrowConversionError::value_conversion(
80 stringify!($name),
81 format!("expected {}, got {:?}", stringify!($hana_variant), other),
82 ));
83 }
84 }
85 self.len += 1;
86 Ok(())
87 }
88
89 fn append_null(&mut self) {
90 self.builder.append_null();
91 self.len += 1;
92 }
93
94 fn finish(&mut self) -> ArrayRef {
95 self.len = 0;
96 Arc::new(self.builder.finish())
97 }
98
99 fn len(&self) -> usize {
100 self.len
101 }
102
103 fn capacity(&self) -> Option<usize> {
104 Some(self.builder.capacity())
105 }
106 }
107 };
108}
109
110impl_primitive_builder!(UInt8BuilderWrapper, UInt8Builder, u8, TINYINT);
115impl_primitive_builder!(Int16BuilderWrapper, Int16Builder, i16, SMALLINT);
116impl_primitive_builder!(Int32BuilderWrapper, Int32Builder, i32, INT);
117impl_primitive_builder!(Int64BuilderWrapper, Int64Builder, i64, BIGINT);
118impl_primitive_builder!(Float32BuilderWrapper, Float32Builder, f32, REAL);
119impl_primitive_builder!(Float64BuilderWrapper, Float64Builder, f64, DOUBLE);
120
121#[cfg(test)]
122mod tests {
123 use arrow_array::{Array, Float32Array, Int16Array, Int32Array, Int64Array, UInt8Array};
124 use hdbconnect::HdbValue;
125
126 use super::*;
127
128 #[test]
133 fn test_int32_builder_wrapper() {
134 let mut builder = Int32BuilderWrapper::new(10);
135
136 assert_eq!(builder.len(), 0);
137 assert!(builder.is_empty());
138
139 builder.append_hana_value(&HdbValue::INT(42)).unwrap();
140 builder.append_null();
141 builder.append_hana_value(&HdbValue::INT(-100)).unwrap();
142
143 assert_eq!(builder.len(), 3);
144
145 let array = builder.finish();
146 assert_eq!(array.len(), 3);
147 assert_eq!(builder.len(), 0);
148 }
149
150 #[test]
151 fn test_int32_builder_default_capacity() {
152 let builder = Int32BuilderWrapper::default_capacity();
153 assert_eq!(builder.len(), 0);
154 assert!(builder.is_empty());
155 }
156
157 #[test]
158 fn test_int32_builder_wrong_type() {
159 let mut builder = Int32BuilderWrapper::new(1);
160 let result = builder.append_hana_value(&HdbValue::STRING("test".to_string()));
161 assert!(result.is_err());
162 assert!(result.unwrap_err().is_value_conversion());
163 }
164
165 #[test]
166 fn test_int32_builder_boundary_values() {
167 let mut builder = Int32BuilderWrapper::new(3);
168 builder.append_hana_value(&HdbValue::INT(i32::MAX)).unwrap();
169 builder.append_hana_value(&HdbValue::INT(i32::MIN)).unwrap();
170 builder.append_hana_value(&HdbValue::INT(0)).unwrap();
171
172 let array = builder.finish();
173 let int_array = array.as_any().downcast_ref::<Int32Array>().unwrap();
174 assert_eq!(int_array.value(0), i32::MAX);
175 assert_eq!(int_array.value(1), i32::MIN);
176 assert_eq!(int_array.value(2), 0);
177 }
178
179 #[test]
180 fn test_int32_builder_reuse() {
181 let mut builder = Int32BuilderWrapper::new(10);
182 builder.append_hana_value(&HdbValue::INT(1)).unwrap();
183 let _ = builder.finish();
184
185 builder.append_hana_value(&HdbValue::INT(2)).unwrap();
186 let array = builder.finish();
187 let int_array = array.as_any().downcast_ref::<Int32Array>().unwrap();
188 assert_eq!(int_array.value(0), 2);
189 }
190
191 #[test]
196 fn test_float64_builder_wrapper() {
197 let mut builder = Float64BuilderWrapper::new(5);
198
199 builder.append_hana_value(&HdbValue::DOUBLE(3.14)).unwrap();
200 builder.append_null();
201
202 let array = builder.finish();
203 assert_eq!(array.len(), 2);
204 }
205
206 #[test]
207 fn test_float64_builder_default_capacity() {
208 let builder = Float64BuilderWrapper::default_capacity();
209 assert_eq!(builder.len(), 0);
210 }
211
212 #[test]
213 fn test_float64_builder_special_values() {
214 let mut builder = Float64BuilderWrapper::new(5);
215 builder
216 .append_hana_value(&HdbValue::DOUBLE(f64::MAX))
217 .unwrap();
218 builder
219 .append_hana_value(&HdbValue::DOUBLE(f64::MIN))
220 .unwrap();
221 builder.append_hana_value(&HdbValue::DOUBLE(0.0)).unwrap();
222 builder.append_hana_value(&HdbValue::DOUBLE(-0.0)).unwrap();
223 builder
224 .append_hana_value(&HdbValue::DOUBLE(f64::INFINITY))
225 .unwrap();
226
227 let array = builder.finish();
228 assert_eq!(array.len(), 5);
229 }
230
231 #[test]
232 fn test_float64_builder_wrong_type() {
233 let mut builder = Float64BuilderWrapper::new(1);
234 let result = builder.append_hana_value(&HdbValue::INT(42));
235 assert!(result.is_err());
236 assert!(result.unwrap_err().is_value_conversion());
237 }
238
239 #[test]
244 fn test_uint8_builder_wrapper() {
245 let mut builder = UInt8BuilderWrapper::new(5);
246
247 builder.append_hana_value(&HdbValue::TINYINT(255)).unwrap();
248 let array = builder.finish();
249 assert_eq!(array.len(), 1);
250 }
251
252 #[test]
253 fn test_uint8_builder_default_capacity() {
254 let builder = UInt8BuilderWrapper::default_capacity();
255 assert_eq!(builder.len(), 0);
256 }
257
258 #[test]
259 fn test_uint8_builder_boundary_values() {
260 let mut builder = UInt8BuilderWrapper::new(3);
261 builder.append_hana_value(&HdbValue::TINYINT(0)).unwrap();
262 builder.append_hana_value(&HdbValue::TINYINT(255)).unwrap();
263 builder.append_hana_value(&HdbValue::TINYINT(128)).unwrap();
264
265 let array = builder.finish();
266 let uint_array = array.as_any().downcast_ref::<UInt8Array>().unwrap();
267 assert_eq!(uint_array.value(0), 0);
268 assert_eq!(uint_array.value(1), 255);
269 assert_eq!(uint_array.value(2), 128);
270 }
271
272 #[test]
273 fn test_uint8_builder_wrong_type() {
274 let mut builder = UInt8BuilderWrapper::new(1);
275 let result = builder.append_hana_value(&HdbValue::STRING("test".to_string()));
276 assert!(result.is_err());
277 }
278
279 #[test]
284 fn test_int16_builder_wrapper() {
285 let mut builder = Int16BuilderWrapper::new(5);
286 builder
287 .append_hana_value(&HdbValue::SMALLINT(32767))
288 .unwrap();
289 builder
290 .append_hana_value(&HdbValue::SMALLINT(-32768))
291 .unwrap();
292 builder.append_null();
293
294 let array = builder.finish();
295 let int_array = array.as_any().downcast_ref::<Int16Array>().unwrap();
296 assert_eq!(int_array.value(0), 32767);
297 assert_eq!(int_array.value(1), -32768);
298 assert!(int_array.is_null(2));
299 }
300
301 #[test]
302 fn test_int16_builder_default_capacity() {
303 let builder = Int16BuilderWrapper::default_capacity();
304 assert_eq!(builder.len(), 0);
305 }
306
307 #[test]
308 fn test_int16_builder_wrong_type() {
309 let mut builder = Int16BuilderWrapper::new(1);
310 let result = builder.append_hana_value(&HdbValue::BIGINT(100));
311 assert!(result.is_err());
312 }
313
314 #[test]
319 fn test_int64_builder_wrapper() {
320 let mut builder = Int64BuilderWrapper::new(5);
321 builder
322 .append_hana_value(&HdbValue::BIGINT(i64::MAX))
323 .unwrap();
324 builder
325 .append_hana_value(&HdbValue::BIGINT(i64::MIN))
326 .unwrap();
327 builder.append_null();
328
329 let array = builder.finish();
330 let int_array = array.as_any().downcast_ref::<Int64Array>().unwrap();
331 assert_eq!(int_array.value(0), i64::MAX);
332 assert_eq!(int_array.value(1), i64::MIN);
333 assert!(int_array.is_null(2));
334 }
335
336 #[test]
337 fn test_int64_builder_default_capacity() {
338 let builder = Int64BuilderWrapper::default_capacity();
339 assert_eq!(builder.len(), 0);
340 }
341
342 #[test]
343 fn test_int64_builder_wrong_type() {
344 let mut builder = Int64BuilderWrapper::new(1);
345 let result = builder.append_hana_value(&HdbValue::DOUBLE(1.0));
346 assert!(result.is_err());
347 }
348
349 #[test]
354 fn test_float32_builder_wrapper() {
355 let mut builder = Float32BuilderWrapper::new(5);
356 builder.append_hana_value(&HdbValue::REAL(1.5)).unwrap();
357 builder.append_hana_value(&HdbValue::REAL(-2.5)).unwrap();
358 builder.append_null();
359
360 let array = builder.finish();
361 let float_array = array.as_any().downcast_ref::<Float32Array>().unwrap();
362 assert!((float_array.value(0) - 1.5).abs() < f32::EPSILON);
363 assert!((float_array.value(1) - (-2.5)).abs() < f32::EPSILON);
364 assert!(float_array.is_null(2));
365 }
366
367 #[test]
368 fn test_float32_builder_default_capacity() {
369 let builder = Float32BuilderWrapper::default_capacity();
370 assert_eq!(builder.len(), 0);
371 }
372
373 #[test]
374 fn test_float32_builder_wrong_type() {
375 let mut builder = Float32BuilderWrapper::new(1);
376 let result = builder.append_hana_value(&HdbValue::INT(42));
377 assert!(result.is_err());
378 }
379
380 #[test]
385 fn test_capacity_hint() {
386 let builder = Int32BuilderWrapper::new(100);
387 assert_eq!(builder.capacity(), Some(100));
388 }
389
390 #[test]
391 fn test_all_builders_debug() {
392 let _ = format!("{:?}", UInt8BuilderWrapper::new(1));
393 let _ = format!("{:?}", Int16BuilderWrapper::new(1));
394 let _ = format!("{:?}", Int32BuilderWrapper::new(1));
395 let _ = format!("{:?}", Int64BuilderWrapper::new(1));
396 let _ = format!("{:?}", Float32BuilderWrapper::new(1));
397 let _ = format!("{:?}", Float64BuilderWrapper::new(1));
398 }
399
400 #[test]
401 fn test_all_builders_null_handling() {
402 let mut uint8 = UInt8BuilderWrapper::new(1);
403 uint8.append_null();
404 assert_eq!(uint8.len(), 1);
405
406 let mut int16 = Int16BuilderWrapper::new(1);
407 int16.append_null();
408 assert_eq!(int16.len(), 1);
409
410 let mut int32 = Int32BuilderWrapper::new(1);
411 int32.append_null();
412 assert_eq!(int32.len(), 1);
413
414 let mut int64 = Int64BuilderWrapper::new(1);
415 int64.append_null();
416 assert_eq!(int64.len(), 1);
417
418 let mut float32 = Float32BuilderWrapper::new(1);
419 float32.append_null();
420 assert_eq!(float32.len(), 1);
421
422 let mut float64 = Float64BuilderWrapper::new(1);
423 float64.append_null();
424 assert_eq!(float64.len(), 1);
425 }
426}