hdbconnect_arrow/builders/
string.rs1use std::sync::Arc;
11
12use arrow_array::ArrayRef;
13use arrow_array::builder::{
14 BinaryBuilder, FixedSizeBinaryBuilder, LargeBinaryBuilder, LargeStringBuilder, StringBuilder,
15};
16
17use crate::Result;
18use crate::traits::builder::HanaCompatibleBuilder;
19use crate::traits::sealed::private::Sealed;
20
21#[derive(Debug)]
27pub struct StringBuilderWrapper {
28 builder: StringBuilder,
29 len: usize,
30}
31
32impl StringBuilderWrapper {
33 #[must_use]
40 pub fn new(capacity: usize, data_capacity: usize) -> Self {
41 Self {
42 builder: StringBuilder::with_capacity(capacity, data_capacity),
43 len: 0,
44 }
45 }
46
47 #[must_use]
49 pub fn default_capacity() -> Self {
50 Self::new(1024, 32 * 1024)
51 }
52}
53
54impl Sealed for StringBuilderWrapper {}
55
56impl HanaCompatibleBuilder for StringBuilderWrapper {
57 fn append_hana_value(&mut self, value: &hdbconnect::HdbValue) -> Result<()> {
58 use hdbconnect::HdbValue;
59
60 match value {
61 HdbValue::STRING(s) => {
62 self.builder.append_value(s);
63 }
64 other => {
66 self.builder.append_value(format!("{other:?}"));
67 }
68 }
69 self.len += 1;
70 Ok(())
71 }
72
73 fn append_null(&mut self) {
74 self.builder.append_null();
75 self.len += 1;
76 }
77
78 fn finish(&mut self) -> ArrayRef {
79 self.len = 0;
80 Arc::new(self.builder.finish())
81 }
82
83 fn len(&self) -> usize {
84 self.len
85 }
86
87 fn capacity(&self) -> Option<usize> {
88 None
90 }
91}
92
93#[derive(Debug)]
95pub struct LargeStringBuilderWrapper {
96 builder: LargeStringBuilder,
97 len: usize,
98}
99
100impl LargeStringBuilderWrapper {
101 #[must_use]
103 pub fn new(capacity: usize, data_capacity: usize) -> Self {
104 Self {
105 builder: LargeStringBuilder::with_capacity(capacity, data_capacity),
106 len: 0,
107 }
108 }
109
110 #[must_use]
112 pub fn default_capacity() -> Self {
113 Self::new(1024, 1024 * 1024) }
115}
116
117impl Sealed for LargeStringBuilderWrapper {}
118
119impl HanaCompatibleBuilder for LargeStringBuilderWrapper {
120 fn append_hana_value(&mut self, value: &hdbconnect::HdbValue) -> Result<()> {
121 use hdbconnect::HdbValue;
122
123 match value {
124 HdbValue::STRING(s) => {
125 self.builder.append_value(s);
126 }
127 other => {
130 self.builder.append_value(format!("{other:?}"));
131 }
132 }
133 self.len += 1;
134 Ok(())
135 }
136
137 fn append_null(&mut self) {
138 self.builder.append_null();
139 self.len += 1;
140 }
141
142 fn finish(&mut self) -> ArrayRef {
143 self.len = 0;
144 Arc::new(self.builder.finish())
145 }
146
147 fn len(&self) -> usize {
148 self.len
149 }
150
151 fn capacity(&self) -> Option<usize> {
152 None
153 }
154}
155
156#[derive(Debug)]
162pub struct BinaryBuilderWrapper {
163 builder: BinaryBuilder,
164 len: usize,
165}
166
167impl BinaryBuilderWrapper {
168 #[must_use]
170 pub fn new(capacity: usize, data_capacity: usize) -> Self {
171 Self {
172 builder: BinaryBuilder::with_capacity(capacity, data_capacity),
173 len: 0,
174 }
175 }
176
177 #[must_use]
179 pub fn default_capacity() -> Self {
180 Self::new(1024, 64 * 1024) }
182}
183
184impl Sealed for BinaryBuilderWrapper {}
185
186impl HanaCompatibleBuilder for BinaryBuilderWrapper {
187 fn append_hana_value(&mut self, value: &hdbconnect::HdbValue) -> Result<()> {
188 use hdbconnect::HdbValue;
189
190 match value {
191 HdbValue::BINARY(bytes) | HdbValue::GEOMETRY(bytes) | HdbValue::POINT(bytes) => {
193 self.builder.append_value(bytes);
194 }
195 other => {
196 return Err(crate::ArrowConversionError::value_conversion(
197 "binary",
198 format!("cannot convert {other:?} to binary"),
199 ));
200 }
201 }
202 self.len += 1;
203 Ok(())
204 }
205
206 fn append_null(&mut self) {
207 self.builder.append_null();
208 self.len += 1;
209 }
210
211 fn finish(&mut self) -> ArrayRef {
212 self.len = 0;
213 Arc::new(self.builder.finish())
214 }
215
216 fn len(&self) -> usize {
217 self.len
218 }
219
220 fn capacity(&self) -> Option<usize> {
221 None
222 }
223}
224
225#[derive(Debug)]
227pub struct LargeBinaryBuilderWrapper {
228 builder: LargeBinaryBuilder,
229 len: usize,
230}
231
232impl LargeBinaryBuilderWrapper {
233 #[must_use]
235 pub fn new(capacity: usize, data_capacity: usize) -> Self {
236 Self {
237 builder: LargeBinaryBuilder::with_capacity(capacity, data_capacity),
238 len: 0,
239 }
240 }
241
242 #[must_use]
244 pub fn default_capacity() -> Self {
245 Self::new(1024, 1024 * 1024) }
247}
248
249impl Sealed for LargeBinaryBuilderWrapper {}
250
251impl HanaCompatibleBuilder for LargeBinaryBuilderWrapper {
252 fn append_hana_value(&mut self, value: &hdbconnect::HdbValue) -> Result<()> {
253 use hdbconnect::HdbValue;
254
255 match value {
256 HdbValue::BINARY(bytes) => {
257 self.builder.append_value(bytes);
258 }
259 other => {
261 return Err(crate::ArrowConversionError::value_conversion(
262 "large_binary",
263 format!("cannot convert {other:?} to binary"),
264 ));
265 }
266 }
267 self.len += 1;
268 Ok(())
269 }
270
271 fn append_null(&mut self) {
272 self.builder.append_null();
273 self.len += 1;
274 }
275
276 fn finish(&mut self) -> ArrayRef {
277 self.len = 0;
278 Arc::new(self.builder.finish())
279 }
280
281 fn len(&self) -> usize {
282 self.len
283 }
284
285 fn capacity(&self) -> Option<usize> {
286 None
287 }
288}
289
290#[derive(Debug)]
292pub struct FixedSizeBinaryBuilderWrapper {
293 builder: FixedSizeBinaryBuilder,
294 byte_width: i32,
295 len: usize,
296}
297
298impl FixedSizeBinaryBuilderWrapper {
299 #[must_use]
306 pub fn new(capacity: usize, byte_width: i32) -> Self {
307 Self {
308 builder: FixedSizeBinaryBuilder::with_capacity(capacity, byte_width),
309 byte_width,
310 len: 0,
311 }
312 }
313}
314
315impl Sealed for FixedSizeBinaryBuilderWrapper {}
316
317impl HanaCompatibleBuilder for FixedSizeBinaryBuilderWrapper {
318 fn append_hana_value(&mut self, value: &hdbconnect::HdbValue) -> Result<()> {
319 use hdbconnect::HdbValue;
320
321 match value {
322 HdbValue::BINARY(bytes) => {
323 #[allow(clippy::cast_sign_loss)]
324 if bytes.len() != self.byte_width as usize {
325 return Err(crate::ArrowConversionError::value_conversion(
326 "fixed_size_binary",
327 format!("expected {} bytes, got {}", self.byte_width, bytes.len()),
328 ));
329 }
330 self.builder.append_value(bytes).map_err(|e| {
331 crate::ArrowConversionError::value_conversion(
332 "fixed_size_binary",
333 e.to_string(),
334 )
335 })?;
336 }
337 other => {
338 return Err(crate::ArrowConversionError::value_conversion(
339 "fixed_size_binary",
340 format!("cannot convert {other:?} to fixed-size binary"),
341 ));
342 }
343 }
344 self.len += 1;
345 Ok(())
346 }
347
348 fn append_null(&mut self) {
349 self.builder.append_null();
350 self.len += 1;
351 }
352
353 fn finish(&mut self) -> ArrayRef {
354 self.len = 0;
355 Arc::new(self.builder.finish())
356 }
357
358 fn len(&self) -> usize {
359 self.len
360 }
361
362 fn capacity(&self) -> Option<usize> {
363 None
364 }
365}
366
367#[cfg(test)]
368mod tests {
369 use arrow_array::{
370 Array, BinaryArray, FixedSizeBinaryArray, LargeBinaryArray, LargeStringArray, StringArray,
371 };
372 use hdbconnect::HdbValue;
373
374 use super::*;
375
376 #[test]
381 fn test_string_builder_new() {
382 let builder = StringBuilderWrapper::new(10, 100);
383 assert_eq!(builder.len(), 0);
384 assert!(builder.capacity().is_none());
385 }
386
387 #[test]
388 fn test_string_builder_default_capacity() {
389 let builder = StringBuilderWrapper::default_capacity();
390 assert_eq!(builder.len(), 0);
391 }
392
393 #[test]
394 fn test_string_builder_append_string() {
395 let mut builder = StringBuilderWrapper::new(10, 100);
396 builder
397 .append_hana_value(&HdbValue::STRING("hello".to_string()))
398 .unwrap();
399 assert_eq!(builder.len(), 1);
400 }
401
402 #[test]
403 fn test_string_builder_append_null() {
404 let mut builder = StringBuilderWrapper::new(10, 100);
405 builder.append_null();
406 assert_eq!(builder.len(), 1);
407
408 let array = builder.finish();
409 let string_array = array.as_any().downcast_ref::<StringArray>().unwrap();
410 assert!(string_array.is_null(0));
411 }
412
413 #[test]
414 fn test_string_builder_append_non_string_type() {
415 let mut builder = StringBuilderWrapper::new(10, 100);
416 builder.append_hana_value(&HdbValue::INT(42)).unwrap();
417 assert_eq!(builder.len(), 1);
418
419 let array = builder.finish();
420 let string_array = array.as_any().downcast_ref::<StringArray>().unwrap();
421 assert!(string_array.value(0).contains("INT"));
422 }
423
424 #[test]
425 fn test_string_builder_finish_and_reuse() {
426 let mut builder = StringBuilderWrapper::new(10, 100);
427 builder
428 .append_hana_value(&HdbValue::STRING("first".to_string()))
429 .unwrap();
430 let _array1 = builder.finish();
431 assert_eq!(builder.len(), 0);
432
433 builder
434 .append_hana_value(&HdbValue::STRING("second".to_string()))
435 .unwrap();
436 let array2 = builder.finish();
437 assert_eq!(array2.len(), 1);
438 }
439
440 #[test]
441 fn test_string_builder_empty_string() {
442 let mut builder = StringBuilderWrapper::new(10, 100);
443 builder
444 .append_hana_value(&HdbValue::STRING(String::new()))
445 .unwrap();
446
447 let array = builder.finish();
448 let string_array = array.as_any().downcast_ref::<StringArray>().unwrap();
449 assert_eq!(string_array.value(0), "");
450 }
451
452 #[test]
453 fn test_string_builder_unicode() {
454 let mut builder = StringBuilderWrapper::new(10, 1000);
455 builder
456 .append_hana_value(&HdbValue::STRING("日本語テスト".to_string()))
457 .unwrap();
458 builder
459 .append_hana_value(&HdbValue::STRING("émojis: 🚀🎉".to_string()))
460 .unwrap();
461
462 let array = builder.finish();
463 let string_array = array.as_any().downcast_ref::<StringArray>().unwrap();
464 assert_eq!(string_array.value(0), "日本語テスト");
465 assert_eq!(string_array.value(1), "émojis: 🚀🎉");
466 }
467
468 #[test]
473 fn test_large_string_builder_new() {
474 let builder = LargeStringBuilderWrapper::new(10, 1000);
475 assert_eq!(builder.len(), 0);
476 }
477
478 #[test]
479 fn test_large_string_builder_default_capacity() {
480 let builder = LargeStringBuilderWrapper::default_capacity();
481 assert_eq!(builder.len(), 0);
482 }
483
484 #[test]
485 fn test_large_string_builder_append_string() {
486 let mut builder = LargeStringBuilderWrapper::new(10, 1000);
487 builder
488 .append_hana_value(&HdbValue::STRING("large text".to_string()))
489 .unwrap();
490
491 let array = builder.finish();
492 let large_string_array = array.as_any().downcast_ref::<LargeStringArray>().unwrap();
493 assert_eq!(large_string_array.value(0), "large text");
494 }
495
496 #[test]
497 fn test_large_string_builder_append_null() {
498 let mut builder = LargeStringBuilderWrapper::new(10, 1000);
499 builder.append_null();
500
501 let array = builder.finish();
502 let large_string_array = array.as_any().downcast_ref::<LargeStringArray>().unwrap();
503 assert!(large_string_array.is_null(0));
504 }
505
506 #[test]
507 fn test_large_string_builder_append_non_string_type() {
508 let mut builder = LargeStringBuilderWrapper::new(10, 1000);
509 builder
510 .append_hana_value(&HdbValue::BIGINT(123456789))
511 .unwrap();
512
513 let array = builder.finish();
514 let large_string_array = array.as_any().downcast_ref::<LargeStringArray>().unwrap();
515 assert!(large_string_array.value(0).contains("BIGINT"));
516 }
517
518 #[test]
523 fn test_binary_builder_new() {
524 let builder = BinaryBuilderWrapper::new(10, 100);
525 assert_eq!(builder.len(), 0);
526 }
527
528 #[test]
529 fn test_binary_builder_default_capacity() {
530 let builder = BinaryBuilderWrapper::default_capacity();
531 assert_eq!(builder.len(), 0);
532 }
533
534 #[test]
535 fn test_binary_builder_append_binary() {
536 let mut builder = BinaryBuilderWrapper::new(10, 100);
537 builder
538 .append_hana_value(&HdbValue::BINARY(vec![1, 2, 3]))
539 .unwrap();
540
541 let array = builder.finish();
542 let binary_array = array.as_any().downcast_ref::<BinaryArray>().unwrap();
543 assert_eq!(binary_array.value(0), &[1, 2, 3]);
544 }
545
546 #[test]
547 fn test_binary_builder_append_null() {
548 let mut builder = BinaryBuilderWrapper::new(10, 100);
549 builder.append_null();
550
551 let array = builder.finish();
552 let binary_array = array.as_any().downcast_ref::<BinaryArray>().unwrap();
553 assert!(binary_array.is_null(0));
554 }
555
556 #[test]
557 fn test_binary_builder_append_geometry() {
558 let mut builder = BinaryBuilderWrapper::new(10, 100);
559 builder
560 .append_hana_value(&HdbValue::GEOMETRY(vec![0x00, 0x01, 0x02]))
561 .unwrap();
562
563 let array = builder.finish();
564 assert_eq!(array.len(), 1);
565 }
566
567 #[test]
568 fn test_binary_builder_append_point() {
569 let mut builder = BinaryBuilderWrapper::new(10, 100);
570 builder
571 .append_hana_value(&HdbValue::POINT(vec![0xAB, 0xCD]))
572 .unwrap();
573
574 let array = builder.finish();
575 assert_eq!(array.len(), 1);
576 }
577
578 #[test]
579 fn test_binary_builder_reject_string() {
580 let mut builder = BinaryBuilderWrapper::new(10, 100);
581 let result = builder.append_hana_value(&HdbValue::STRING("text".to_string()));
582 assert!(result.is_err());
583 assert!(result.unwrap_err().is_value_conversion());
584 }
585
586 #[test]
587 fn test_binary_builder_empty_binary() {
588 let mut builder = BinaryBuilderWrapper::new(10, 100);
589 builder
590 .append_hana_value(&HdbValue::BINARY(vec![]))
591 .unwrap();
592
593 let array = builder.finish();
594 let binary_array = array.as_any().downcast_ref::<BinaryArray>().unwrap();
595 assert!(binary_array.value(0).is_empty());
596 }
597
598 #[test]
603 fn test_large_binary_builder_new() {
604 let builder = LargeBinaryBuilderWrapper::new(10, 1000);
605 assert_eq!(builder.len(), 0);
606 }
607
608 #[test]
609 fn test_large_binary_builder_default_capacity() {
610 let builder = LargeBinaryBuilderWrapper::default_capacity();
611 assert_eq!(builder.len(), 0);
612 }
613
614 #[test]
615 fn test_large_binary_builder_append_binary() {
616 let mut builder = LargeBinaryBuilderWrapper::new(10, 1000);
617 builder
618 .append_hana_value(&HdbValue::BINARY(vec![1, 2, 3, 4, 5]))
619 .unwrap();
620
621 let array = builder.finish();
622 let large_binary_array = array.as_any().downcast_ref::<LargeBinaryArray>().unwrap();
623 assert_eq!(large_binary_array.value(0), &[1, 2, 3, 4, 5]);
624 }
625
626 #[test]
627 fn test_large_binary_builder_append_null() {
628 let mut builder = LargeBinaryBuilderWrapper::new(10, 1000);
629 builder.append_null();
630
631 let array = builder.finish();
632 let large_binary_array = array.as_any().downcast_ref::<LargeBinaryArray>().unwrap();
633 assert!(large_binary_array.is_null(0));
634 }
635
636 #[test]
637 fn test_large_binary_builder_reject_string() {
638 let mut builder = LargeBinaryBuilderWrapper::new(10, 1000);
639 let result = builder.append_hana_value(&HdbValue::STRING("text".to_string()));
640 assert!(result.is_err());
641 assert!(result.unwrap_err().is_value_conversion());
642 }
643
644 #[test]
649 fn test_fixed_size_binary_builder_new() {
650 let builder = FixedSizeBinaryBuilderWrapper::new(10, 4);
651 assert_eq!(builder.len(), 0);
652 assert_eq!(builder.byte_width, 4);
653 }
654
655 #[test]
656 fn test_fixed_size_binary_builder_correct_size() {
657 let mut builder = FixedSizeBinaryBuilderWrapper::new(10, 4);
658 builder
659 .append_hana_value(&HdbValue::BINARY(vec![1, 2, 3, 4]))
660 .unwrap();
661
662 let array = builder.finish();
663 let fixed_binary = array
664 .as_any()
665 .downcast_ref::<FixedSizeBinaryArray>()
666 .unwrap();
667 assert_eq!(fixed_binary.value(0), &[1, 2, 3, 4]);
668 }
669
670 #[test]
671 fn test_fixed_size_binary_builder_wrong_size_smaller() {
672 let mut builder = FixedSizeBinaryBuilderWrapper::new(10, 4);
673 let result = builder.append_hana_value(&HdbValue::BINARY(vec![1, 2]));
674 assert!(result.is_err());
675 let err = result.unwrap_err();
676 assert!(err.is_value_conversion());
677 assert!(err.to_string().contains("expected 4 bytes"));
678 }
679
680 #[test]
681 fn test_fixed_size_binary_builder_wrong_size_larger() {
682 let mut builder = FixedSizeBinaryBuilderWrapper::new(10, 4);
683 let result = builder.append_hana_value(&HdbValue::BINARY(vec![1, 2, 3, 4, 5, 6]));
684 assert!(result.is_err());
685 }
686
687 #[test]
688 fn test_fixed_size_binary_builder_append_null() {
689 let mut builder = FixedSizeBinaryBuilderWrapper::new(10, 4);
690 builder.append_null();
691
692 let array = builder.finish();
693 let fixed_binary = array
694 .as_any()
695 .downcast_ref::<FixedSizeBinaryArray>()
696 .unwrap();
697 assert!(fixed_binary.is_null(0));
698 }
699
700 #[test]
701 fn test_fixed_size_binary_builder_reject_non_binary() {
702 let mut builder = FixedSizeBinaryBuilderWrapper::new(10, 4);
703 let result = builder.append_hana_value(&HdbValue::INT(42));
704 assert!(result.is_err());
705 assert!(result.unwrap_err().is_value_conversion());
706 }
707
708 #[test]
709 fn test_fixed_size_binary_builder_different_widths() {
710 let mut builder8 = FixedSizeBinaryBuilderWrapper::new(10, 8);
712 builder8
713 .append_hana_value(&HdbValue::BINARY(vec![1, 2, 3, 4, 5, 6, 7, 8]))
714 .unwrap();
715 assert_eq!(builder8.len(), 1);
716
717 let mut builder16 = FixedSizeBinaryBuilderWrapper::new(10, 16);
719 builder16
720 .append_hana_value(&HdbValue::BINARY(vec![0; 16]))
721 .unwrap();
722 assert_eq!(builder16.len(), 1);
723 }
724}