1use std::sync::{Arc, LazyLock};
7
8use arrow_array::ArrayRef;
9use arrow_array::builder::Decimal128Builder;
10use num_bigint::BigInt;
11
12use crate::Result;
13use crate::traits::builder::HanaCompatibleBuilder;
14use crate::traits::sealed::private::Sealed;
15use crate::types::hana::{DecimalPrecision, DecimalScale};
16
17const POWERS_OF_10_I128: [i128; 39] = [
20 1, 10, 100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000, 100_000_000, 1_000_000_000, 10_000_000_000, 100_000_000_000, 1_000_000_000_000, 10_000_000_000_000, 100_000_000_000_000, 1_000_000_000_000_000, 10_000_000_000_000_000, 100_000_000_000_000_000, 1_000_000_000_000_000_000, 10_000_000_000_000_000_000, 100_000_000_000_000_000_000, 1_000_000_000_000_000_000_000, 10_000_000_000_000_000_000_000, 100_000_000_000_000_000_000_000, 1_000_000_000_000_000_000_000_000, 10_000_000_000_000_000_000_000_000, 100_000_000_000_000_000_000_000_000, 1_000_000_000_000_000_000_000_000_000, 10_000_000_000_000_000_000_000_000_000, 100_000_000_000_000_000_000_000_000_000, 1_000_000_000_000_000_000_000_000_000_000, 10_000_000_000_000_000_000_000_000_000_000, 100_000_000_000_000_000_000_000_000_000_000, 1_000_000_000_000_000_000_000_000_000_000_000, 10_000_000_000_000_000_000_000_000_000_000_000, 100_000_000_000_000_000_000_000_000_000_000_000, 1_000_000_000_000_000_000_000_000_000_000_000_000, 10_000_000_000_000_000_000_000_000_000_000_000_000, 100_000_000_000_000_000_000_000_000_000_000_000_000, ];
60
61static POWERS_OF_10_BIGINT: LazyLock<[BigInt; 39]> =
64 LazyLock::new(|| std::array::from_fn(|i| BigInt::from(POWERS_OF_10_I128[i])));
65
66#[inline]
69fn scale_up_i128(mantissa: i128, scale_diff: i64) -> Option<i128> {
70 let idx = usize::try_from(scale_diff).ok()?;
71 let multiplier = POWERS_OF_10_I128.get(idx)?;
72 mantissa.checked_mul(*multiplier)
73}
74
75#[inline]
78fn scale_down_i128(mantissa: i128, scale_diff: i64) -> Option<i128> {
79 let idx = usize::try_from(scale_diff).ok()?;
80 let divisor = POWERS_OF_10_I128.get(idx)?;
81 Some(mantissa / divisor)
82}
83
84fn scale_up_bigint(mantissa: &BigInt, scale_diff: i64) -> BigInt {
86 let exp = usize::try_from(scale_diff).unwrap_or(0).min(38);
87 mantissa * &POWERS_OF_10_BIGINT[exp]
88}
89
90fn scale_down_bigint(mantissa: &BigInt, scale_diff: i64) -> BigInt {
92 let exp = usize::try_from(scale_diff).unwrap_or(0).min(38);
93 mantissa / &POWERS_OF_10_BIGINT[exp]
94}
95
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub struct DecimalConfig {
101 precision: DecimalPrecision,
102 scale: DecimalScale,
103}
104
105impl DecimalConfig {
106 pub fn new(precision: u8, scale: i8) -> Result<Self> {
112 let prec = DecimalPrecision::new(precision)?;
113 let scl = DecimalScale::new(scale, prec)?;
114 Ok(Self {
115 precision: prec,
116 scale: scl,
117 })
118 }
119
120 #[must_use]
122 pub const fn precision(&self) -> u8 {
123 self.precision.value()
124 }
125
126 #[must_use]
128 pub const fn scale(&self) -> i8 {
129 self.scale.value()
130 }
131}
132
133#[derive(Debug)]
137pub struct Decimal128BuilderWrapper {
138 builder: Decimal128Builder,
139 config: DecimalConfig,
140 len: usize,
141}
142
143impl Decimal128BuilderWrapper {
144 #[must_use]
156 pub fn new(capacity: usize, precision: u8, scale: i8) -> Self {
157 let config = DecimalConfig::new(precision, scale)
158 .expect("decimal config should be validated before builder creation");
159
160 let builder = Decimal128Builder::with_capacity(capacity)
161 .with_data_type(arrow_schema::DataType::Decimal128(precision, scale));
162
163 Self {
164 builder,
165 config,
166 len: 0,
167 }
168 }
169
170 #[must_use]
172 pub fn from_config(capacity: usize, config: DecimalConfig) -> Self {
173 let builder = Decimal128Builder::with_capacity(capacity).with_data_type(
174 arrow_schema::DataType::Decimal128(config.precision(), config.scale()),
175 );
176
177 Self {
178 builder,
179 config,
180 len: 0,
181 }
182 }
183
184 fn convert_decimal_slow(&self, mantissa: &BigInt, scale_diff: i64) -> Result<i128> {
187 use num_traits::ToPrimitive;
188
189 let scaled_value = if scale_diff >= 0 {
190 scale_up_bigint(mantissa, scale_diff)
191 } else {
192 scale_down_bigint(mantissa, -scale_diff)
193 };
194
195 scaled_value.to_i128().ok_or_else(|| {
196 crate::ArrowConversionError::decimal_overflow(
197 self.config.precision(),
198 self.config.scale(),
199 )
200 })
201 }
202
203 fn convert_decimal(&self, value: &hdbconnect::HdbValue) -> Result<i128> {
212 use hdbconnect::HdbValue;
213 use num_traits::ToPrimitive;
214
215 match value {
216 HdbValue::DECIMAL(decimal) => {
217 let (mantissa, exponent) = decimal.as_bigint_and_scale();
222 let target_scale = i64::from(self.config.scale());
223 let scale_diff = target_scale - exponent;
224
225 if let Some(m) = mantissa.to_i128() {
227 if scale_diff >= 0 {
228 if let Some(result) = scale_up_i128(m, scale_diff) {
229 return Ok(result);
230 }
231 } else if let Some(result) = scale_down_i128(m, -scale_diff) {
232 return Ok(result);
233 }
234 }
235
236 self.convert_decimal_slow(&mantissa, scale_diff)
239 }
240 other => Err(crate::ArrowConversionError::value_conversion(
241 "decimal",
242 format!("expected DECIMAL, got {:?}", std::mem::discriminant(other)),
243 )),
244 }
245 }
246}
247
248impl Sealed for Decimal128BuilderWrapper {}
249
250impl HanaCompatibleBuilder for Decimal128BuilderWrapper {
251 fn append_hana_value(&mut self, value: &hdbconnect::HdbValue) -> Result<()> {
252 let i128_val = self.convert_decimal(value)?;
253 self.builder.append_value(i128_val);
254 self.len += 1;
255 Ok(())
256 }
257
258 fn append_null(&mut self) {
259 self.builder.append_null();
260 self.len += 1;
261 }
262
263 fn finish(&mut self) -> ArrayRef {
264 self.len = 0;
265 Arc::new(self.builder.finish())
266 }
267
268 fn len(&self) -> usize {
269 self.len
270 }
271
272 fn capacity(&self) -> Option<usize> {
273 Some(self.builder.capacity())
274 }
275}
276
277#[cfg(test)]
278mod tests {
279 use arrow_array::Array;
280
281 use super::*;
282
283 #[test]
288 fn test_decimal_config_valid() {
289 let config = DecimalConfig::new(18, 2).unwrap();
290 assert_eq!(config.precision(), 18);
291 assert_eq!(config.scale(), 2);
292 }
293
294 #[test]
295 fn test_decimal_config_invalid_precision() {
296 assert!(DecimalConfig::new(0, 0).is_err());
297 assert!(DecimalConfig::new(39, 0).is_err());
298 }
299
300 #[test]
301 fn test_decimal_config_invalid_scale() {
302 assert!(DecimalConfig::new(18, -1).is_err());
303 assert!(DecimalConfig::new(18, 20).is_err());
304 }
305
306 #[test]
307 fn test_decimal_config_min_precision() {
308 let config = DecimalConfig::new(1, 0).unwrap();
309 assert_eq!(config.precision(), 1);
310 assert_eq!(config.scale(), 0);
311 }
312
313 #[test]
314 fn test_decimal_config_max_precision() {
315 let config = DecimalConfig::new(38, 10).unwrap();
316 assert_eq!(config.precision(), 38);
317 assert_eq!(config.scale(), 10);
318 }
319
320 #[test]
321 fn test_decimal_config_scale_equals_precision() {
322 let config = DecimalConfig::new(5, 5).unwrap();
323 assert_eq!(config.precision(), 5);
324 assert_eq!(config.scale(), 5);
325 }
326
327 #[test]
328 fn test_decimal_config_zero_scale() {
329 let config = DecimalConfig::new(10, 0).unwrap();
330 assert_eq!(config.precision(), 10);
331 assert_eq!(config.scale(), 0);
332 }
333
334 #[test]
335 fn test_decimal_config_equality() {
336 let config1 = DecimalConfig::new(18, 2).unwrap();
337 let config2 = DecimalConfig::new(18, 2).unwrap();
338 let config3 = DecimalConfig::new(18, 3).unwrap();
339 assert_eq!(config1, config2);
340 assert_ne!(config1, config3);
341 }
342
343 #[test]
344 fn test_decimal_config_copy() {
345 let config1 = DecimalConfig::new(18, 2).unwrap();
346 let config2 = config1;
347 assert_eq!(config1, config2);
348 }
349
350 #[test]
355 fn test_decimal_builder_creation() {
356 let builder = Decimal128BuilderWrapper::new(100, 18, 2);
357 assert_eq!(builder.len(), 0);
358 assert_eq!(builder.config.precision(), 18);
359 assert_eq!(builder.config.scale(), 2);
360 }
361
362 #[test]
363 fn test_decimal_builder_from_config() {
364 let config = DecimalConfig::new(10, 4).unwrap();
365 let builder = Decimal128BuilderWrapper::from_config(50, config);
366 assert_eq!(builder.len(), 0);
367 assert_eq!(builder.config.precision(), 10);
368 assert_eq!(builder.config.scale(), 4);
369 }
370
371 #[test]
372 fn test_decimal_builder_capacity() {
373 let builder = Decimal128BuilderWrapper::new(100, 18, 2);
374 assert!(builder.capacity().is_some());
375 }
376
377 #[test]
378 fn test_decimal_builder_is_empty() {
379 let builder = Decimal128BuilderWrapper::new(10, 18, 2);
380 assert!(builder.is_empty());
381 }
382
383 #[test]
388 fn test_decimal_builder_append_null() {
389 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
390 builder.append_null();
391 assert_eq!(builder.len(), 1);
392
393 let array = builder.finish();
394 assert!(array.is_null(0));
395 }
396
397 #[test]
398 fn test_decimal_builder_multiple_nulls() {
399 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
400 builder.append_null();
401 builder.append_null();
402 builder.append_null();
403 assert_eq!(builder.len(), 3);
404
405 let array = builder.finish();
406 assert_eq!(array.len(), 3);
407 assert!(array.is_null(0));
408 assert!(array.is_null(1));
409 assert!(array.is_null(2));
410 }
411
412 #[test]
417 fn test_decimal_builder_finish_resets_len() {
418 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
419 builder.append_null();
420 builder.append_null();
421 assert_eq!(builder.len(), 2);
422
423 let _ = builder.finish();
424 assert_eq!(builder.len(), 0);
425 }
426
427 #[test]
428 fn test_decimal_builder_finish_empty() {
429 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
430 let array = builder.finish();
431 assert_eq!(array.len(), 0);
432 }
433
434 #[test]
435 fn test_decimal_builder_reuse_after_finish() {
436 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
437 builder.append_null();
438 let array1 = builder.finish();
439 assert_eq!(array1.len(), 1);
440
441 builder.append_null();
442 builder.append_null();
443 let array2 = builder.finish();
444 assert_eq!(array2.len(), 2);
445 }
446
447 #[test]
452 fn test_decimal_builder_high_precision() {
453 let builder = Decimal128BuilderWrapper::new(10, 38, 10);
454 assert_eq!(builder.config.precision(), 38);
455 assert_eq!(builder.config.scale(), 10);
456 }
457
458 #[test]
459 fn test_decimal_builder_low_precision() {
460 let builder = Decimal128BuilderWrapper::new(10, 1, 0);
461 assert_eq!(builder.config.precision(), 1);
462 assert_eq!(builder.config.scale(), 0);
463 }
464
465 #[test]
466 fn test_decimal_builder_zero_scale() {
467 let builder = Decimal128BuilderWrapper::new(10, 10, 0);
468 assert_eq!(builder.config.precision(), 10);
469 assert_eq!(builder.config.scale(), 0);
470 }
471
472 #[test]
473 fn test_decimal_builder_scale_equals_precision() {
474 let builder = Decimal128BuilderWrapper::new(10, 5, 5);
475 assert_eq!(builder.config.precision(), 5);
476 assert_eq!(builder.config.scale(), 5);
477 }
478
479 #[test]
484 fn test_decimal_builder_len_increments() {
485 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
486 assert_eq!(builder.len(), 0);
487 builder.append_null();
488 assert_eq!(builder.len(), 1);
489 builder.append_null();
490 assert_eq!(builder.len(), 2);
491 }
492
493 #[test]
494 fn test_decimal_builder_reset() {
495 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
496 builder.append_null();
497 builder.append_null();
498 assert_eq!(builder.len(), 2);
499
500 builder.reset();
501 assert_eq!(builder.len(), 0);
502 assert!(builder.is_empty());
503 }
504
505 #[test]
510 fn test_powers_of_10_i128_correctness() {
511 for (i, &power) in POWERS_OF_10_I128.iter().enumerate() {
512 let expected = 10_i128.pow(i as u32);
513 assert_eq!(power, expected, "POWERS_OF_10_I128[{i}] mismatch");
514 }
515 }
516
517 #[test]
518 fn test_powers_of_10_bigint_correctness() {
519 for (i, power) in POWERS_OF_10_BIGINT.iter().enumerate() {
520 let expected = BigInt::from(10_i128).pow(i as u32);
521 assert_eq!(power, &expected, "POWERS_OF_10_BIGINT[{i}] mismatch");
522 }
523 }
524
525 #[test]
526 fn test_powers_of_10_i128_boundary_values() {
527 assert_eq!(POWERS_OF_10_I128[0], 1);
528 assert_eq!(
529 POWERS_OF_10_I128[38],
530 100_000_000_000_000_000_000_000_000_000_000_000_000
531 );
532 }
533
534 #[test]
539 fn test_scale_up_i128_simple() {
540 assert_eq!(scale_up_i128(100, 2), Some(10000));
541 }
542
543 #[test]
544 fn test_scale_up_i128_zero_scale_diff() {
545 assert_eq!(scale_up_i128(12345, 0), Some(12345));
546 }
547
548 #[test]
549 fn test_scale_up_i128_max_scale_diff() {
550 assert_eq!(scale_up_i128(1, 38), Some(POWERS_OF_10_I128[38]));
551 }
552
553 #[test]
554 fn test_scale_up_i128_overflow() {
555 assert_eq!(scale_up_i128(i128::MAX, 1), None);
557 }
558
559 #[test]
560 fn test_scale_up_i128_negative_scale_diff() {
561 assert_eq!(scale_up_i128(100, -1), None);
562 }
563
564 #[test]
565 fn test_scale_up_i128_out_of_range_scale_diff() {
566 assert_eq!(scale_up_i128(1, 39), None);
567 }
568
569 #[test]
570 fn test_scale_down_i128_simple() {
571 assert_eq!(scale_down_i128(12345, 2), Some(123));
572 }
573
574 #[test]
575 fn test_scale_down_i128_zero_scale_diff() {
576 assert_eq!(scale_down_i128(12345, 0), Some(12345));
577 }
578
579 #[test]
580 fn test_scale_down_i128_truncation() {
581 assert_eq!(scale_down_i128(12399, 2), Some(123));
582 }
583
584 #[test]
585 fn test_scale_down_i128_negative_scale_diff() {
586 assert_eq!(scale_down_i128(100, -1), None);
587 }
588
589 #[test]
590 fn test_scale_down_i128_out_of_range() {
591 assert_eq!(scale_down_i128(1, 39), None);
592 }
593
594 #[test]
599 fn test_convert_decimal_slow_scale_up() {
600 let builder = Decimal128BuilderWrapper::new(10, 18, 2);
601 let mantissa = BigInt::from(100_i128);
602 assert_eq!(builder.convert_decimal_slow(&mantissa, 2).unwrap(), 10000);
603 }
604
605 #[test]
606 fn test_convert_decimal_slow_scale_down() {
607 let builder = Decimal128BuilderWrapper::new(10, 18, 0);
608 let mantissa = BigInt::from(12345_i128);
609 assert_eq!(builder.convert_decimal_slow(&mantissa, -2).unwrap(), 123);
610 }
611
612 #[test]
613 fn test_convert_decimal_slow_large_mantissa() {
614 let builder = Decimal128BuilderWrapper::new(10, 38, 0);
615 let mantissa = BigInt::from(i128::MAX);
617 assert_eq!(
618 builder.convert_decimal_slow(&mantissa, 0).unwrap(),
619 i128::MAX
620 );
621 }
622
623 #[test]
624 fn test_convert_decimal_slow_overflow() {
625 let builder = Decimal128BuilderWrapper::new(10, 38, 0);
626 let mantissa = BigInt::from(i128::MAX) * 10;
628 assert!(builder.convert_decimal_slow(&mantissa, 0).is_err());
629 }
630
631 #[cfg(feature = "test-utils")]
636 mod convert_decimal_tests {
637 use arrow_array::Decimal128Array;
638
639 use super::*;
640 use crate::traits::row::MockRowBuilder;
641
642 fn convert_and_get_value(precision: u8, scale: i8, decimal_str: &str) -> i128 {
644 let mut builder = Decimal128BuilderWrapper::new(10, precision, scale);
645 let row = MockRowBuilder::new().decimal_str(decimal_str).build();
646 builder.append_hana_value(&row[0]).unwrap();
647 let array = builder.finish();
648 let decimal_array = array.as_any().downcast_ref::<Decimal128Array>().unwrap();
649 decimal_array.value(0)
650 }
651
652 #[test]
657 fn test_convert_decimal_simple_value() {
658 let value = convert_and_get_value(18, 2, "123.45");
660 assert_eq!(value, 12345);
661 }
662
663 #[test]
664 fn test_convert_decimal_integer_value() {
665 let value = convert_and_get_value(10, 0, "100");
667 assert_eq!(value, 100);
668 }
669
670 #[test]
671 fn test_convert_decimal_large_value() {
672 let value = convert_and_get_value(18, 2, "9999999.99");
674 assert_eq!(value, 999999999);
675 }
676
677 #[test]
682 fn test_convert_decimal_scale_up_integer_to_decimal() {
683 let value = convert_and_get_value(10, 2, "100");
685 assert_eq!(value, 10000);
686 }
687
688 #[test]
689 fn test_convert_decimal_scale_up_by_one() {
690 let value = convert_and_get_value(10, 2, "123.4");
692 assert_eq!(value, 12340);
693 }
694
695 #[test]
696 fn test_convert_decimal_scale_up_by_multiple() {
697 let value = convert_and_get_value(10, 4, "5");
699 assert_eq!(value, 50000);
700 }
701
702 #[test]
707 fn test_convert_decimal_scale_down_truncate() {
708 let value = convert_and_get_value(10, 2, "123.456");
710 assert_eq!(value, 12345);
711 }
712
713 #[test]
714 fn test_convert_decimal_scale_down_to_integer() {
715 let value = convert_and_get_value(10, 0, "123.99");
717 assert_eq!(value, 123);
718 }
719
720 #[test]
721 fn test_convert_decimal_scale_down_multiple_places() {
722 let value = convert_and_get_value(18, 2, "1.23456789");
724 assert_eq!(value, 123);
725 }
726
727 #[test]
732 fn test_convert_decimal_scale_match_exact() {
733 let value = convert_and_get_value(18, 2, "123.45");
735 assert_eq!(value, 12345);
736 }
737
738 #[test]
739 fn test_convert_decimal_scale_match_high_scale() {
740 let value = convert_and_get_value(38, 18, "1.234567890123456789");
742 assert_eq!(value, 1_234_567_890_123_456_789_i128);
743 }
744
745 #[test]
750 fn test_convert_decimal_negative_simple() {
751 let value = convert_and_get_value(18, 2, "-123.45");
753 assert_eq!(value, -12345);
754 }
755
756 #[test]
757 fn test_convert_decimal_negative_scale_up() {
758 let value = convert_and_get_value(10, 2, "-100");
760 assert_eq!(value, -10000);
761 }
762
763 #[test]
764 fn test_convert_decimal_negative_scale_down() {
765 let value = convert_and_get_value(10, 2, "-123.456");
767 assert_eq!(value, -12345);
768 }
769
770 #[test]
771 fn test_convert_decimal_negative_large() {
772 let value = convert_and_get_value(18, 2, "-9999999.99");
774 assert_eq!(value, -999999999);
775 }
776
777 #[test]
782 fn test_convert_decimal_zero() {
783 let value = convert_and_get_value(10, 2, "0");
784 assert_eq!(value, 0);
785 }
786
787 #[test]
788 fn test_convert_decimal_zero_with_scale() {
789 let value = convert_and_get_value(10, 2, "0.00");
791 assert_eq!(value, 0);
792 }
793
794 #[test]
795 fn test_convert_decimal_negative_zero() {
796 let value = convert_and_get_value(10, 2, "-0");
798 assert_eq!(value, 0);
799 }
800
801 #[test]
806 fn test_convert_decimal_max_precision_integer() {
807 let value = convert_and_get_value(38, 0, "99999999999999999999999999999999999999");
811 assert_eq!(
812 value,
813 99_999_999_999_999_999_999_999_999_999_999_999_999_i128
814 );
815 }
816
817 #[test]
818 fn test_convert_decimal_max_precision_with_scale() {
819 let value = convert_and_get_value(38, 4, "9999999999999999999999999999999999.9999");
822 assert_eq!(
823 value,
824 99_999_999_999_999_999_999_999_999_999_999_999_999_i128
825 );
826 }
827
828 #[test]
829 fn test_convert_decimal_i128_max_boundary() {
830 let value = convert_and_get_value(38, 0, "170141183460469231731687303715884105727");
833 assert_eq!(value, i128::MAX);
834 }
835
836 #[test]
837 fn test_convert_decimal_i128_min_boundary() {
838 let value = convert_and_get_value(38, 0, "-170141183460469231731687303715884105728");
841 assert_eq!(value, i128::MIN);
842 }
843
844 #[test]
849 fn test_convert_decimal_overflow_scale_up() {
850 let mut builder = Decimal128BuilderWrapper::new(10, 38, 10);
853 let row = MockRowBuilder::new()
855 .decimal_str("17014118346046923173168730371588410573")
856 .build();
857 let result = builder.append_hana_value(&row[0]);
858 assert!(result.is_err());
859 }
860
861 #[test]
862 fn test_convert_decimal_overflow_large_value() {
863 let mut builder = Decimal128BuilderWrapper::new(10, 38, 0);
865 let row = MockRowBuilder::new()
867 .decimal_str("999999999999999999999999999999999999999")
868 .build();
869 let result = builder.append_hana_value(&row[0]);
870 assert!(result.is_err());
871 }
872
873 #[test]
878 fn test_convert_decimal_wrong_type_int() {
879 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
880 let row = MockRowBuilder::new().int(42).build();
881 let result = builder.append_hana_value(&row[0]);
882 assert!(result.is_err());
883 }
884
885 #[test]
886 fn test_convert_decimal_wrong_type_string() {
887 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
888 let row = MockRowBuilder::new().string("123.45").build();
889 let result = builder.append_hana_value(&row[0]);
890 assert!(result.is_err());
891 }
892
893 #[test]
894 fn test_convert_decimal_wrong_type_null() {
895 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
896 let row = MockRowBuilder::new().null().build();
897 let result = builder.append_hana_value(&row[0]);
898 assert!(result.is_err());
901 }
902
903 #[test]
904 fn test_convert_decimal_wrong_type_double() {
905 let mut builder = Decimal128BuilderWrapper::new(10, 18, 2);
906 let row = MockRowBuilder::new().double(123.45).build();
907 let result = builder.append_hana_value(&row[0]);
908 assert!(result.is_err());
909 }
910
911 #[test]
916 fn test_convert_decimal_very_small_value() {
917 let value = convert_and_get_value(18, 8, "0.00000001");
919 assert_eq!(value, 1);
920 }
921
922 #[test]
923 fn test_convert_decimal_leading_zeros() {
924 let value = convert_and_get_value(18, 2, "00123.45");
926 assert_eq!(value, 12345);
927 }
928
929 #[test]
930 fn test_convert_decimal_trailing_zeros() {
931 let value = convert_and_get_value(18, 2, "123.450");
933 assert_eq!(value, 12345);
934 }
935
936 #[test]
937 fn test_convert_decimal_scientific_notation() {
938 let value = convert_and_get_value(10, 0, "1.23e2");
940 assert_eq!(value, 123);
941 }
942
943 #[test]
944 fn test_convert_decimal_scientific_notation_negative_exp() {
945 let value = convert_and_get_value(10, 0, "12300e-2");
947 assert_eq!(value, 123);
948 }
949
950 #[test]
955 fn test_fast_path_boundary_i128_max() {
956 let value = convert_and_get_value(38, 0, "170141183460469231731687303715884105727");
958 assert_eq!(value, i128::MAX);
959 }
960
961 #[test]
962 fn test_fast_path_boundary_i128_min() {
963 let value = convert_and_get_value(38, 0, "-170141183460469231731687303715884105728");
965 assert_eq!(value, i128::MIN);
966 }
967
968 #[test]
969 fn test_fast_path_boundary_scale_38() {
970 let value = convert_and_get_value(38, 38, "1");
972 assert_eq!(value, POWERS_OF_10_I128[38]);
973 }
974
975 #[test]
980 fn test_slow_path_fallback_overflow_triggers_slow_path() {
981 let value = convert_and_get_value(38, 1, "10000000000000000000000000000000000000");
984 assert_eq!(value, POWERS_OF_10_I128[38]);
985 }
986
987 #[test]
988 fn test_slow_path_mantissa_exceeds_i128() {
989 let mut builder = Decimal128BuilderWrapper::new(10, 38, 0);
992 let row = MockRowBuilder::new()
994 .decimal_str("1000000000000000000000000000000000000000")
995 .build();
996 let result = builder.append_hana_value(&row[0]);
999 assert!(result.is_err());
1001 }
1002 }
1003}