Skip to main content

hdbconnect_arrow/builders/
boolean.rs

1//! Boolean type builder for Arrow boolean arrays.
2
3use std::sync::Arc;
4
5use arrow_array::ArrayRef;
6use arrow_array::builder::BooleanBuilder;
7
8use crate::Result;
9use crate::traits::builder::HanaCompatibleBuilder;
10use crate::traits::sealed::private::Sealed;
11
12/// Builder for Arrow Boolean arrays (HANA BOOLEAN).
13#[derive(Debug)]
14pub struct BooleanBuilderWrapper {
15    builder: BooleanBuilder,
16    len: usize,
17}
18
19impl BooleanBuilderWrapper {
20    /// Create a new boolean builder.
21    #[must_use]
22    pub fn new(capacity: usize) -> Self {
23        Self {
24            builder: BooleanBuilder::with_capacity(capacity),
25            len: 0,
26        }
27    }
28
29    /// Create with default capacity.
30    #[must_use]
31    pub fn default_capacity() -> Self {
32        Self::new(1024)
33    }
34}
35
36impl Sealed for BooleanBuilderWrapper {}
37
38impl HanaCompatibleBuilder for BooleanBuilderWrapper {
39    fn append_hana_value(&mut self, value: &hdbconnect::HdbValue) -> Result<()> {
40        use hdbconnect::HdbValue;
41
42        match value {
43            HdbValue::BOOLEAN(b) => {
44                self.builder.append_value(*b);
45            }
46            other => {
47                return Err(crate::ArrowConversionError::value_conversion(
48                    "boolean",
49                    format!("expected BOOLEAN, got {other:?}"),
50                ));
51            }
52        }
53        self.len += 1;
54        Ok(())
55    }
56
57    fn append_null(&mut self) {
58        self.builder.append_null();
59        self.len += 1;
60    }
61
62    fn finish(&mut self) -> ArrayRef {
63        self.len = 0;
64        Arc::new(self.builder.finish())
65    }
66
67    fn len(&self) -> usize {
68        self.len
69    }
70
71    fn capacity(&self) -> Option<usize> {
72        Some(self.builder.capacity())
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use arrow_array::{Array, BooleanArray};
79    use hdbconnect::HdbValue;
80
81    use super::*;
82
83    #[test]
84    fn test_boolean_builder() {
85        let mut builder = BooleanBuilderWrapper::new(10);
86
87        builder.append_hana_value(&HdbValue::BOOLEAN(true)).unwrap();
88        builder.append_null();
89        builder
90            .append_hana_value(&HdbValue::BOOLEAN(false))
91            .unwrap();
92
93        assert_eq!(builder.len(), 3);
94        let array = builder.finish();
95        assert_eq!(array.len(), 3);
96    }
97
98    #[test]
99    fn test_boolean_builder_default_capacity() {
100        let builder = BooleanBuilderWrapper::default_capacity();
101        assert_eq!(builder.len(), 0);
102        assert!(builder.is_empty());
103        assert!(builder.capacity().is_some());
104    }
105
106    #[test]
107    fn test_boolean_builder_new_with_capacity() {
108        let builder = BooleanBuilderWrapper::new(100);
109        assert_eq!(builder.len(), 0);
110        // Capacity may be rounded up by the underlying builder
111        assert!(builder.capacity().is_some());
112        assert!(builder.capacity().unwrap() >= 100);
113    }
114
115    #[test]
116    fn test_boolean_builder_true_values() {
117        let mut builder = BooleanBuilderWrapper::new(5);
118        for _ in 0..5 {
119            builder.append_hana_value(&HdbValue::BOOLEAN(true)).unwrap();
120        }
121        assert_eq!(builder.len(), 5);
122        let array = builder.finish();
123        let bool_array = array.as_any().downcast_ref::<BooleanArray>().unwrap();
124        for i in 0..5 {
125            assert!(bool_array.value(i));
126        }
127    }
128
129    #[test]
130    fn test_boolean_builder_false_values() {
131        let mut builder = BooleanBuilderWrapper::new(5);
132        for _ in 0..5 {
133            builder
134                .append_hana_value(&HdbValue::BOOLEAN(false))
135                .unwrap();
136        }
137        let array = builder.finish();
138        let bool_array = array.as_any().downcast_ref::<BooleanArray>().unwrap();
139        for i in 0..5 {
140            assert!(!bool_array.value(i));
141        }
142    }
143
144    #[test]
145    fn test_boolean_builder_mixed_values() {
146        let mut builder = BooleanBuilderWrapper::new(4);
147        builder.append_hana_value(&HdbValue::BOOLEAN(true)).unwrap();
148        builder
149            .append_hana_value(&HdbValue::BOOLEAN(false))
150            .unwrap();
151        builder.append_hana_value(&HdbValue::BOOLEAN(true)).unwrap();
152        builder
153            .append_hana_value(&HdbValue::BOOLEAN(false))
154            .unwrap();
155
156        let array = builder.finish();
157        let bool_array = array.as_any().downcast_ref::<BooleanArray>().unwrap();
158        assert!(bool_array.value(0));
159        assert!(!bool_array.value(1));
160        assert!(bool_array.value(2));
161        assert!(!bool_array.value(3));
162    }
163
164    #[test]
165    fn test_boolean_builder_null_values() {
166        let mut builder = BooleanBuilderWrapper::new(3);
167        builder.append_null();
168        builder.append_null();
169        builder.append_null();
170
171        let array = builder.finish();
172        let bool_array = array.as_any().downcast_ref::<BooleanArray>().unwrap();
173        assert!(bool_array.is_null(0));
174        assert!(bool_array.is_null(1));
175        assert!(bool_array.is_null(2));
176    }
177
178    #[test]
179    fn test_boolean_builder_mixed_with_nulls() {
180        let mut builder = BooleanBuilderWrapper::new(5);
181        builder.append_hana_value(&HdbValue::BOOLEAN(true)).unwrap();
182        builder.append_null();
183        builder
184            .append_hana_value(&HdbValue::BOOLEAN(false))
185            .unwrap();
186        builder.append_null();
187        builder.append_hana_value(&HdbValue::BOOLEAN(true)).unwrap();
188
189        let array = builder.finish();
190        let bool_array = array.as_any().downcast_ref::<BooleanArray>().unwrap();
191        assert!(bool_array.value(0) && !bool_array.is_null(0));
192        assert!(bool_array.is_null(1));
193        assert!(!bool_array.value(2) && !bool_array.is_null(2));
194        assert!(bool_array.is_null(3));
195        assert!(bool_array.value(4) && !bool_array.is_null(4));
196    }
197
198    #[test]
199    fn test_boolean_builder_wrong_type_int() {
200        let mut builder = BooleanBuilderWrapper::new(1);
201        let result = builder.append_hana_value(&HdbValue::INT(42));
202        assert!(result.is_err());
203        let err = result.unwrap_err();
204        assert!(err.is_value_conversion());
205        assert!(err.to_string().contains("BOOLEAN"));
206    }
207
208    #[test]
209    fn test_boolean_builder_wrong_type_string() {
210        let mut builder = BooleanBuilderWrapper::new(1);
211        let result = builder.append_hana_value(&HdbValue::STRING("true".to_string()));
212        assert!(result.is_err());
213        assert!(result.unwrap_err().is_value_conversion());
214    }
215
216    #[test]
217    fn test_boolean_builder_wrong_type_bigint() {
218        let mut builder = BooleanBuilderWrapper::new(1);
219        let result = builder.append_hana_value(&HdbValue::BIGINT(1));
220        assert!(result.is_err());
221        assert!(result.unwrap_err().is_value_conversion());
222    }
223
224    #[test]
225    fn test_boolean_builder_finish_resets_len() {
226        let mut builder = BooleanBuilderWrapper::new(10);
227        builder.append_hana_value(&HdbValue::BOOLEAN(true)).unwrap();
228        builder.append_hana_value(&HdbValue::BOOLEAN(true)).unwrap();
229        assert_eq!(builder.len(), 2);
230
231        let _ = builder.finish();
232        assert_eq!(builder.len(), 0);
233        assert!(builder.is_empty());
234    }
235
236    #[test]
237    fn test_boolean_builder_reuse_after_finish() {
238        let mut builder = BooleanBuilderWrapper::new(10);
239        builder.append_hana_value(&HdbValue::BOOLEAN(true)).unwrap();
240        let array1 = builder.finish();
241        assert_eq!(array1.len(), 1);
242
243        builder
244            .append_hana_value(&HdbValue::BOOLEAN(false))
245            .unwrap();
246        builder
247            .append_hana_value(&HdbValue::BOOLEAN(false))
248            .unwrap();
249        let array2 = builder.finish();
250        assert_eq!(array2.len(), 2);
251    }
252
253    #[test]
254    fn test_boolean_builder_debug() {
255        let builder = BooleanBuilderWrapper::new(10);
256        let debug_str = format!("{:?}", builder);
257        assert!(debug_str.contains("BooleanBuilderWrapper"));
258    }
259
260    #[test]
261    fn test_boolean_builder_empty_finish() {
262        let mut builder = BooleanBuilderWrapper::new(10);
263        let array = builder.finish();
264        assert_eq!(array.len(), 0);
265    }
266}