1use crate::error::ConversionError;
7use crate::types::{
8 conversion::{
9 parse_date_to_days as parse_date_to_days_impl,
10 parse_decimal_to_i128 as parse_decimal_to_i128_impl,
11 parse_timestamp_to_micros as parse_timestamp_to_micros_impl,
12 },
13 ExasolType,
14};
15use arrow::array::{
16 ArrayRef, BinaryBuilder, BooleanBuilder, Date32Builder, Decimal128Builder, Float64Builder,
17 IntervalMonthDayNanoBuilder, StringBuilder, TimestampMicrosecondBuilder,
18};
19use serde_json::Value;
20use std::sync::Arc;
21
22pub trait ArrayBuilder {
24 fn append_value(
31 &mut self,
32 value: &Value,
33 row: usize,
34 column: usize,
35 ) -> Result<(), ConversionError>;
36
37 fn finish(&mut self) -> Result<ArrayRef, ConversionError>;
39}
40
41pub fn build_array(
42 exasol_type: &ExasolType,
43 values: &[&Value],
44 column: usize,
45) -> Result<ArrayRef, ConversionError> {
46 match exasol_type {
47 ExasolType::Boolean => build_boolean_array(values, column),
48 ExasolType::Char { .. } | ExasolType::Varchar { .. } => build_string_array(values, column),
49 ExasolType::Decimal { precision, scale } => {
51 build_decimal128_array(values, *precision, *scale, column)
52 }
53 ExasolType::Double => build_double_array(values, column),
54 ExasolType::Date => build_date_array(values, column),
55 ExasolType::Timestamp {
56 with_local_time_zone,
57 } => build_timestamp_array(values, *with_local_time_zone, column),
58 ExasolType::IntervalYearToMonth => build_interval_year_to_month_array(values, column),
59 ExasolType::IntervalDayToSecond { .. } => {
60 build_interval_day_to_second_array(values, column)
61 }
62 ExasolType::Geometry { .. } | ExasolType::Hashtype { .. } => {
63 build_binary_array(values, column)
64 }
65 }
66}
67
68fn build_boolean_array(values: &[&Value], column: usize) -> Result<ArrayRef, ConversionError> {
69 let mut builder = BooleanBuilder::with_capacity(values.len());
70
71 for (row, value) in values.iter().enumerate() {
72 if value.is_null() {
73 builder.append_null();
74 } else if let Some(b) = value.as_bool() {
75 builder.append_value(b);
76 } else {
77 return Err(ConversionError::ValueConversionFailed {
78 row,
79 column,
80 message: format!("Expected boolean, got: {:?}", value),
81 });
82 }
83 }
84
85 Ok(Arc::new(builder.finish()))
86}
87
88fn estimate_string_capacity(values: &[&Value]) -> usize {
89 const SAMPLE_SIZE: usize = 10;
90 const DEFAULT_AVG_LEN: usize = 32;
91
92 let mut total_len = 0;
93 let mut count = 0;
94
95 for value in values.iter().take(SAMPLE_SIZE) {
96 if let Some(s) = value.as_str() {
97 total_len += s.len();
98 count += 1;
99 }
100 }
101
102 if count > 0 {
103 let avg_len = total_len / count;
104 (avg_len + 8) * values.len()
106 } else {
107 DEFAULT_AVG_LEN * values.len()
108 }
109}
110
111fn build_string_array(values: &[&Value], column: usize) -> Result<ArrayRef, ConversionError> {
112 let estimated_bytes = estimate_string_capacity(values);
114 let mut builder = StringBuilder::with_capacity(values.len(), estimated_bytes);
115
116 for (row, value) in values.iter().enumerate() {
117 if value.is_null() {
118 builder.append_null();
119 } else if let Some(s) = value.as_str() {
120 builder.append_value(s);
122 } else {
123 return Err(ConversionError::ValueConversionFailed {
124 row,
125 column,
126 message: format!("Expected string, got: {:?}", value),
127 });
128 }
129 }
130
131 Ok(Arc::new(builder.finish()))
132}
133
134fn validate_decimal_precision(
149 value_str: &str,
150 precision: u8,
151 _scale: i8,
152 row: usize,
153 column: usize,
154) -> Result<(), ConversionError> {
155 let digits: String = value_str.chars().filter(|c| c.is_ascii_digit()).collect();
157
158 let total_digits = digits.len();
159 let max_digits = precision as usize;
160
161 let significant_digits = digits.trim_start_matches('0');
163 let significant_count = if significant_digits.is_empty() {
164 1 } else {
166 significant_digits.len()
167 };
168
169 if significant_count > max_digits {
170 return Err(ConversionError::NumericOverflow { row, column });
171 }
172
173 if total_digits > max_digits + 1 {
176 return Err(ConversionError::NumericOverflow { row, column });
178 }
179
180 Ok(())
181}
182
183fn build_decimal128_array(
184 values: &[&Value],
185 precision: u8,
186 scale: i8,
187 column: usize,
188) -> Result<ArrayRef, ConversionError> {
189 let mut builder = Decimal128Builder::with_capacity(values.len())
190 .with_precision_and_scale(precision, scale)
191 .map_err(|e| ConversionError::ArrowError(e.to_string()))?;
192
193 for (row, value) in values.iter().enumerate() {
194 if value.is_null() {
195 builder.append_null();
196 } else {
197 let decimal_value = parse_decimal_to_i128(value, precision, scale, row, column)?;
198 builder.append_value(decimal_value);
199 }
200 }
201
202 Ok(Arc::new(builder.finish()))
203}
204
205fn parse_decimal_to_i128(
207 value: &Value,
208 precision: u8,
209 scale: i8,
210 row: usize,
211 column: usize,
212) -> Result<i128, ConversionError> {
213 if let Some(n) = value.as_i64() {
215 return Ok((n as i128) * 10_i128.pow(scale as u32));
216 } else if let Some(n) = value.as_f64() {
217 let scaled = (n * 10_f64.powi(scale as i32)).round();
219 return scaled
220 .to_string()
221 .parse::<i128>()
222 .map_err(|_| ConversionError::NumericOverflow { row, column });
223 }
224
225 let value_str = value
227 .as_str()
228 .ok_or_else(|| ConversionError::ValueConversionFailed {
229 row,
230 column,
231 message: format!("Expected numeric value, got: {:?}", value),
232 })?;
233
234 validate_decimal_precision(value_str, precision, scale, row, column)?;
236
237 parse_decimal_to_i128_impl(value_str, scale).map_err(|e| {
239 ConversionError::ValueConversionFailed {
240 row,
241 column,
242 message: e,
243 }
244 })
245}
246
247fn build_double_array(values: &[&Value], column: usize) -> Result<ArrayRef, ConversionError> {
248 let mut builder = Float64Builder::with_capacity(values.len());
249
250 for (row, value) in values.iter().enumerate() {
251 if value.is_null() {
252 builder.append_null();
253 } else if let Some(f) = value.as_f64() {
254 builder.append_value(f);
255 } else if let Some(i) = value.as_i64() {
256 builder.append_value(i as f64);
257 } else if let Some(s) = value.as_str() {
258 let f = match s {
260 "Infinity" => f64::INFINITY,
261 "-Infinity" => f64::NEG_INFINITY,
262 "NaN" => f64::NAN,
263 _ => s
264 .parse::<f64>()
265 .map_err(|_| ConversionError::ValueConversionFailed {
266 row,
267 column,
268 message: format!("Invalid float value: {}", s),
269 })?,
270 };
271 builder.append_value(f);
272 } else {
273 return Err(ConversionError::ValueConversionFailed {
274 row,
275 column,
276 message: format!("Expected number, got: {:?}", value),
277 });
278 }
279 }
280
281 Ok(Arc::new(builder.finish()))
282}
283
284fn build_date_array(values: &[&Value], column: usize) -> Result<ArrayRef, ConversionError> {
285 let mut builder = Date32Builder::with_capacity(values.len());
286
287 for (row, value) in values.iter().enumerate() {
288 if value.is_null() {
289 builder.append_null();
290 } else if let Some(s) = value.as_str() {
291 let days = parse_date_to_days(s, row, column)?;
293 builder.append_value(days);
294 } else {
295 return Err(ConversionError::ValueConversionFailed {
296 row,
297 column,
298 message: format!("Expected date string, got: {:?}", value),
299 });
300 }
301 }
302
303 Ok(Arc::new(builder.finish()))
304}
305
306fn parse_date_to_days(date_str: &str, row: usize, column: usize) -> Result<i32, ConversionError> {
308 parse_date_to_days_impl(date_str).map_err(|e| ConversionError::ValueConversionFailed {
309 row,
310 column,
311 message: e,
312 })
313}
314
315fn build_timestamp_array(
316 values: &[&Value],
317 _with_local_time_zone: bool,
318 column: usize,
319) -> Result<ArrayRef, ConversionError> {
320 let mut builder = TimestampMicrosecondBuilder::with_capacity(values.len());
321
322 for (row, value) in values.iter().enumerate() {
323 if value.is_null() {
324 builder.append_null();
325 } else if let Some(s) = value.as_str() {
326 let micros = parse_timestamp_to_micros(s, row, column)?;
328 builder.append_value(micros);
329 } else {
330 return Err(ConversionError::ValueConversionFailed {
331 row,
332 column,
333 message: format!("Expected timestamp string, got: {:?}", value),
334 });
335 }
336 }
337
338 Ok(Arc::new(builder.finish()))
339}
340
341fn parse_timestamp_to_micros(
343 timestamp_str: &str,
344 row: usize,
345 column: usize,
346) -> Result<i64, ConversionError> {
347 parse_timestamp_to_micros_impl(timestamp_str).map_err(|e| {
348 ConversionError::ValueConversionFailed {
349 row,
350 column,
351 message: e,
352 }
353 })
354}
355
356fn build_interval_year_to_month_array(
357 values: &[&Value],
358 column: usize,
359) -> Result<ArrayRef, ConversionError> {
360 let mut builder = IntervalMonthDayNanoBuilder::with_capacity(values.len());
361
362 for (row, value) in values.iter().enumerate() {
363 if value.is_null() {
364 builder.append_null();
365 } else if let Some(s) = value.as_str() {
366 let months = parse_interval_year_to_month(s, row, column)?;
368 let interval = arrow::datatypes::IntervalMonthDayNano {
370 months,
371 days: 0,
372 nanoseconds: 0,
373 };
374 builder.append_value(interval);
375 } else {
376 return Err(ConversionError::ValueConversionFailed {
377 row,
378 column,
379 message: format!("Expected interval string, got: {:?}", value),
380 });
381 }
382 }
383
384 Ok(Arc::new(builder.finish()))
385}
386
387fn parse_interval_year_to_month(
389 interval_str: &str,
390 row: usize,
391 column: usize,
392) -> Result<i32, ConversionError> {
393 let is_negative = interval_str.starts_with('-');
395 let parts: Vec<&str> = interval_str
396 .trim_start_matches(&['+', '-'][..])
397 .split('-')
398 .collect();
399
400 if parts.len() != 2 {
401 return Err(ConversionError::ValueConversionFailed {
402 row,
403 column,
404 message: format!("Invalid interval format: {}", interval_str),
405 });
406 }
407
408 let years: i32 = parts[0]
409 .parse()
410 .map_err(|_| ConversionError::ValueConversionFailed {
411 row,
412 column,
413 message: format!("Invalid years: {}", parts[0]),
414 })?;
415
416 let months: i32 = parts[1]
417 .parse()
418 .map_err(|_| ConversionError::ValueConversionFailed {
419 row,
420 column,
421 message: format!("Invalid months: {}", parts[1]),
422 })?;
423
424 let total_months = years * 12 + months;
425 Ok(if is_negative {
426 -total_months
427 } else {
428 total_months
429 })
430}
431
432fn build_interval_day_to_second_array(
433 values: &[&Value],
434 column: usize,
435) -> Result<ArrayRef, ConversionError> {
436 let mut builder = IntervalMonthDayNanoBuilder::with_capacity(values.len());
437
438 for (row, value) in values.iter().enumerate() {
439 if value.is_null() {
440 builder.append_null();
441 } else if let Some(s) = value.as_str() {
442 let (days, nanos) = parse_interval_day_to_second(s, row, column)?;
444 let interval = arrow::datatypes::IntervalMonthDayNano {
446 months: 0,
447 days,
448 nanoseconds: nanos,
449 };
450 builder.append_value(interval);
451 } else {
452 return Err(ConversionError::ValueConversionFailed {
453 row,
454 column,
455 message: format!("Expected interval string, got: {:?}", value),
456 });
457 }
458 }
459
460 Ok(Arc::new(builder.finish()))
461}
462
463fn parse_interval_day_to_second(
465 interval_str: &str,
466 row: usize,
467 column: usize,
468) -> Result<(i32, i64), ConversionError> {
469 let is_negative = interval_str.starts_with('-');
471 let trimmed = interval_str.trim_start_matches(&['+', '-'][..]);
472 let parts: Vec<&str> = trimmed.split(' ').collect();
473
474 if parts.is_empty() {
475 return Err(ConversionError::ValueConversionFailed {
476 row,
477 column,
478 message: format!("Invalid interval format: {}", interval_str),
479 });
480 }
481
482 let days: i32 = parts[0]
483 .parse()
484 .map_err(|_| ConversionError::ValueConversionFailed {
485 row,
486 column,
487 message: format!("Invalid days: {}", parts[0]),
488 })?;
489
490 let mut nanos: i64 = 0;
491
492 if parts.len() > 1 {
493 let time_parts: Vec<&str> = parts[1].split(':').collect();
494 if time_parts.len() >= 2 {
495 let hours: i64 =
496 time_parts[0]
497 .parse()
498 .map_err(|_| ConversionError::ValueConversionFailed {
499 row,
500 column,
501 message: format!("Invalid hours: {}", time_parts[0]),
502 })?;
503
504 let minutes: i64 =
505 time_parts[1]
506 .parse()
507 .map_err(|_| ConversionError::ValueConversionFailed {
508 row,
509 column,
510 message: format!("Invalid minutes: {}", time_parts[1]),
511 })?;
512
513 nanos += hours * 3600 * 1_000_000_000;
514 nanos += minutes * 60 * 1_000_000_000;
515
516 if time_parts.len() >= 3 {
517 let sec_parts: Vec<&str> = time_parts[2].split('.').collect();
518 let seconds: i64 =
519 sec_parts[0]
520 .parse()
521 .map_err(|_| ConversionError::ValueConversionFailed {
522 row,
523 column,
524 message: format!("Invalid seconds: {}", sec_parts[0]),
525 })?;
526
527 nanos += seconds * 1_000_000_000;
528
529 if sec_parts.len() > 1 {
530 let frac = sec_parts[1];
532 let frac_nanos = if frac.len() <= 9 {
533 let padding = 9 - frac.len();
534 let padded = format!("{}{}", frac, "0".repeat(padding));
535 padded.parse::<i64>().unwrap_or(0)
536 } else {
537 frac[..9].parse::<i64>().unwrap_or(0)
538 };
539 nanos += frac_nanos;
540 }
541 }
542 }
543 }
544
545 Ok(if is_negative {
546 (-days, -nanos)
547 } else {
548 (days, nanos)
549 })
550}
551
552fn build_binary_array(values: &[&Value], column: usize) -> Result<ArrayRef, ConversionError> {
553 const SAMPLE_SIZE: usize = 10;
556 let sample_count = values.len().min(SAMPLE_SIZE);
557 let sample_total: usize = values
558 .iter()
559 .take(SAMPLE_SIZE)
560 .filter_map(|v| v.as_str())
561 .map(|s| s.len() / 2)
562 .sum();
563
564 let estimated_bytes = if sample_count > 0 {
565 let avg_size = (sample_total / sample_count).max(1);
566 avg_size * values.len()
567 } else {
568 values.len() * 32 };
570
571 let mut builder = BinaryBuilder::with_capacity(values.len(), estimated_bytes.max(1024));
572
573 for (row, value) in values.iter().enumerate() {
574 if value.is_null() {
575 builder.append_null();
576 } else if let Some(s) = value.as_str() {
577 let bytes = decode_hex(s).map_err(|_| ConversionError::ValueConversionFailed {
579 row,
580 column,
581 message: format!("Invalid hex string: {}", s),
582 })?;
583 builder.append_value(&bytes);
584 } else {
585 return Err(ConversionError::ValueConversionFailed {
586 row,
587 column,
588 message: format!("Expected hex string, got: {:?}", value),
589 });
590 }
591 }
592
593 Ok(Arc::new(builder.finish()))
594}
595
596fn decode_hex(s: &str) -> Result<Vec<u8>, ()> {
598 if !s.len().is_multiple_of(2) {
599 return Err(());
600 }
601
602 (0..s.len())
603 .step_by(2)
604 .map(|i| u8::from_str_radix(&s[i..i + 2], 16).map_err(|_| ()))
605 .collect()
606}
607
608#[cfg(test)]
609mod tests {
610 use super::*;
611 use serde_json::json;
612
613 fn to_refs(values: &[Value]) -> Vec<&Value> {
615 values.iter().collect()
616 }
617
618 #[test]
619 fn test_build_boolean_array() {
620 let values = vec![json!(true), json!(false), json!(null), json!(true)];
621 let refs = to_refs(&values);
622 let array = build_boolean_array(&refs, 0).unwrap();
623 assert_eq!(array.len(), 4);
624 assert_eq!(array.null_count(), 1);
625 }
626
627 #[test]
628 fn test_build_string_array() {
629 let values = vec![json!("hello"), json!("world"), json!(null), json!("test")];
630 let refs = to_refs(&values);
631 let array = build_string_array(&refs, 0).unwrap();
632 assert_eq!(array.len(), 4);
633 assert_eq!(array.null_count(), 1);
634 }
635
636 #[test]
637 fn test_build_decimal128_array() {
638 let values = vec![json!("123.45"), json!("678.90"), json!(null)];
639 let refs = to_refs(&values);
640 let array = build_decimal128_array(&refs, 10, 2, 0).unwrap();
641 assert_eq!(array.len(), 3);
642 assert_eq!(array.null_count(), 1);
643 }
644
645 #[test]
646 fn test_build_double_array() {
647 let values = vec![json!(1.5), json!(2.7), json!(null), json!("Infinity")];
648 let refs = to_refs(&values);
649 let array = build_double_array(&refs, 0).unwrap();
650 assert_eq!(array.len(), 4);
651 assert_eq!(array.null_count(), 1);
652 }
653
654 #[test]
655 fn test_parse_date_to_days() {
656 let days = parse_date_to_days("1970-01-01", 0, 0).unwrap();
658 assert_eq!(days, 0);
659
660 let days = parse_date_to_days("1970-01-02", 0, 0).unwrap();
662 assert_eq!(days, 1);
663 }
664
665 #[test]
666 fn test_parse_timestamp_to_micros() {
667 let micros = parse_timestamp_to_micros("1970-01-01 00:00:00", 0, 0).unwrap();
669 assert_eq!(micros, 0);
670
671 let micros = parse_timestamp_to_micros("1970-01-01 00:00:01", 0, 0).unwrap();
673 assert_eq!(micros, 1_000_000);
674 }
675
676 #[test]
677 fn test_parse_interval_year_to_month() {
678 let months = parse_interval_year_to_month("+01-06", 0, 0).unwrap();
679 assert_eq!(months, 18); let months = parse_interval_year_to_month("-02-03", 0, 0).unwrap();
682 assert_eq!(months, -27); }
684
685 #[test]
686 fn test_parse_interval_day_to_second() {
687 let (days, nanos) = parse_interval_day_to_second("+01 12:30:45.123456789", 0, 0).unwrap();
688 assert_eq!(days, 1);
689 assert_eq!(
690 nanos,
691 12 * 3600 * 1_000_000_000 + 30 * 60 * 1_000_000_000 + 45 * 1_000_000_000 + 123_456_789
692 );
693 }
694
695 #[test]
696 fn test_decode_hex() {
697 let bytes = decode_hex("48656c6c6f").unwrap();
698 assert_eq!(bytes, b"Hello");
699
700 let bytes = decode_hex("").unwrap();
701 assert_eq!(bytes, b"");
702
703 assert!(decode_hex("xyz").is_err());
704 assert!(decode_hex("1").is_err()); }
706
707 #[test]
708 fn test_parse_decimal_to_i128() {
709 let result = parse_decimal_to_i128(&json!("123"), 10, 2, 0, 0).unwrap();
711 assert_eq!(result, 12300); let result = parse_decimal_to_i128(&json!("123.45"), 10, 2, 0, 0).unwrap();
715 assert_eq!(result, 12345); let result = parse_decimal_to_i128(&json!("-123.45"), 10, 2, 0, 0).unwrap();
719 assert_eq!(result, -12345);
720
721 let result = parse_decimal_to_i128(&json!(123), 10, 2, 0, 0).unwrap();
723 assert_eq!(result, 12300);
724 }
725
726 #[test]
727 fn test_invalid_conversions() {
728 let values = vec![json!("not a bool")];
730 let refs = to_refs(&values);
731 assert!(build_boolean_array(&refs, 0).is_err());
732
733 let values = vec![json!("2024-13-01")]; let refs = to_refs(&values);
736 assert!(build_date_array(&refs, 0).is_err());
737
738 let values = vec![json!("zzz")];
740 let refs = to_refs(&values);
741 assert!(build_binary_array(&refs, 0).is_err());
742 }
743
744 #[test]
745 fn test_validate_decimal_precision() {
746 assert!(validate_decimal_precision("12345", 10, 2, 0, 0).is_ok());
748
749 assert!(validate_decimal_precision("123.45", 10, 2, 0, 0).is_ok());
751
752 assert!(validate_decimal_precision("-12345", 10, 2, 0, 0).is_ok());
754
755 assert!(validate_decimal_precision("123456", 5, 2, 0, 0).is_err());
757
758 assert!(validate_decimal_precision("00123", 5, 2, 0, 0).is_ok());
760
761 assert!(validate_decimal_precision("0", 1, 0, 0, 0).is_ok());
763
764 assert!(validate_decimal_precision("000", 5, 0, 0, 0).is_ok());
766 }
767
768 #[test]
769 fn test_decimal_precision_overflow() {
770 let values = vec![json!("12345678901234567890")]; let refs = to_refs(&values);
773 let result = build_decimal128_array(&refs, 10, 2, 0);
774 assert!(result.is_err());
775
776 let values = vec![json!("12345")]; let refs = to_refs(&values);
779 let result = build_decimal128_array(&refs, 10, 2, 0);
780 assert!(result.is_ok());
781 }
782
783 #[test]
784 fn test_estimate_string_capacity() {
785 let values = vec![json!("hello"), json!("world"), json!("test")];
787 let refs = to_refs(&values);
788 let capacity = estimate_string_capacity(&refs);
789 assert!(capacity > 0);
791 assert!(capacity >= 15); let empty_values: Vec<Value> = vec![];
795 let empty_refs = to_refs(&empty_values);
796 let empty_capacity = estimate_string_capacity(&empty_refs);
797 assert_eq!(empty_capacity, 0);
798
799 let null_values = vec![json!(null), json!(null), json!(null)];
801 let null_refs = to_refs(&null_values);
802 let null_capacity = estimate_string_capacity(&null_refs);
803 assert!(null_capacity > 0);
804
805 let mixed_values = vec![json!("hello"), json!(null), json!("world")];
807 let mixed_refs = to_refs(&mixed_values);
808 let mixed_capacity = estimate_string_capacity(&mixed_refs);
809 assert!(mixed_capacity > 0);
810 }
811
812 #[test]
817 fn test_build_array_dispatches_to_boolean() {
818 let values = vec![json!(true), json!(false)];
819 let refs = to_refs(&values);
820 let result = build_array(&ExasolType::Boolean, &refs, 0).unwrap();
821 assert_eq!(result.len(), 2);
822 }
823
824 #[test]
825 fn test_build_array_dispatches_to_char() {
826 let values = vec![json!("abc"), json!("def")];
827 let refs = to_refs(&values);
828 let result = build_array(&ExasolType::Char { size: 3 }, &refs, 0).unwrap();
829 assert_eq!(result.len(), 2);
830 }
831
832 #[test]
833 fn test_build_array_dispatches_to_varchar() {
834 let values = vec![json!("hello"), json!("world")];
835 let refs = to_refs(&values);
836 let result = build_array(&ExasolType::Varchar { size: 100 }, &refs, 0).unwrap();
837 assert_eq!(result.len(), 2);
838 }
839
840 #[test]
841 fn test_build_array_dispatches_to_decimal() {
842 let values = vec![json!("123.45"), json!("678.90")];
843 let refs = to_refs(&values);
844 let result = build_array(
845 &ExasolType::Decimal {
846 precision: 10,
847 scale: 2,
848 },
849 &refs,
850 0,
851 )
852 .unwrap();
853 assert_eq!(result.len(), 2);
854 }
855
856 #[test]
857 fn test_build_array_dispatches_to_double() {
858 let values = vec![json!(1.5), json!(2.5)];
859 let refs = to_refs(&values);
860 let result = build_array(&ExasolType::Double, &refs, 0).unwrap();
861 assert_eq!(result.len(), 2);
862 }
863
864 #[test]
865 fn test_build_array_dispatches_to_date() {
866 let values = vec![json!("2024-01-15"), json!("2024-06-20")];
867 let refs = to_refs(&values);
868 let result = build_array(&ExasolType::Date, &refs, 0).unwrap();
869 assert_eq!(result.len(), 2);
870 }
871
872 #[test]
873 fn test_build_array_dispatches_to_timestamp_without_tz() {
874 let values = vec![json!("2024-01-15 10:30:00"), json!("2024-06-20 14:45:30")];
875 let refs = to_refs(&values);
876 let result = build_array(
877 &ExasolType::Timestamp {
878 with_local_time_zone: false,
879 },
880 &refs,
881 0,
882 )
883 .unwrap();
884 assert_eq!(result.len(), 2);
885 }
886
887 #[test]
888 fn test_build_array_dispatches_to_timestamp_with_tz() {
889 let values = vec![json!("2024-01-15 10:30:00"), json!("2024-06-20 14:45:30")];
890 let refs = to_refs(&values);
891 let result = build_array(
892 &ExasolType::Timestamp {
893 with_local_time_zone: true,
894 },
895 &refs,
896 0,
897 )
898 .unwrap();
899 assert_eq!(result.len(), 2);
900 }
901
902 #[test]
903 fn test_build_array_dispatches_to_interval_year_to_month() {
904 let values = vec![json!("+01-06"), json!("-02-03")];
905 let refs = to_refs(&values);
906 let result = build_array(&ExasolType::IntervalYearToMonth, &refs, 0).unwrap();
907 assert_eq!(result.len(), 2);
908 }
909
910 #[test]
911 fn test_build_array_dispatches_to_interval_day_to_second() {
912 let values = vec![json!("+01 12:30:45"), json!("-02 08:15:30")];
913 let refs = to_refs(&values);
914 let result =
915 build_array(&ExasolType::IntervalDayToSecond { precision: 3 }, &refs, 0).unwrap();
916 assert_eq!(result.len(), 2);
917 }
918
919 #[test]
920 fn test_build_array_dispatches_to_geometry() {
921 let values = vec![json!("48656c6c6f"), json!("576f726c64")];
922 let refs = to_refs(&values);
923 let result = build_array(&ExasolType::Geometry { srid: Some(4326) }, &refs, 0).unwrap();
924 assert_eq!(result.len(), 2);
925 }
926
927 #[test]
928 fn test_build_array_dispatches_to_hashtype() {
929 let values = vec![json!("deadbeef"), json!("cafebabe")];
930 let refs = to_refs(&values);
931 let result = build_array(&ExasolType::Hashtype { byte_size: 16 }, &refs, 0).unwrap();
932 assert_eq!(result.len(), 2);
933 }
934
935 #[test]
940 fn test_build_date_array_with_valid_dates() {
941 let values = vec![
942 json!("2024-01-15"),
943 json!("2023-06-20"),
944 json!("1970-01-01"),
945 ];
946 let refs = to_refs(&values);
947 let result = build_date_array(&refs, 0).unwrap();
948 assert_eq!(result.len(), 3);
949 assert_eq!(result.null_count(), 0);
950 }
951
952 #[test]
953 fn test_build_date_array_with_null_values() {
954 let values = vec![json!("2024-01-15"), json!(null), json!("2023-06-20")];
955 let refs = to_refs(&values);
956 let result = build_date_array(&refs, 0).unwrap();
957 assert_eq!(result.len(), 3);
958 assert_eq!(result.null_count(), 1);
959 }
960
961 #[test]
962 fn test_build_date_array_invalid_format_not_string() {
963 let values = vec![json!(12345)];
964 let refs = to_refs(&values);
965 let result = build_date_array(&refs, 0);
966 assert!(result.is_err());
967 match result.unwrap_err() {
968 ConversionError::ValueConversionFailed { message, .. } => {
969 assert!(message.contains("Expected date string"));
970 }
971 _ => panic!("Expected ValueConversionFailed"),
972 }
973 }
974
975 #[test]
976 fn test_build_date_array_invalid_date_format() {
977 let values = vec![json!("2024/01/15")]; let refs = to_refs(&values);
979 let result = build_date_array(&refs, 0);
980 assert!(result.is_err());
981 }
982
983 #[test]
984 fn test_build_date_array_invalid_month_out_of_range() {
985 let values = vec![json!("2024-13-01")]; let refs = to_refs(&values);
987 let result = build_date_array(&refs, 0);
988 assert!(result.is_err());
989 }
990
991 #[test]
992 fn test_build_date_array_invalid_day_out_of_range() {
993 let values = vec![json!("2024-01-32")]; let refs = to_refs(&values);
995 let result = build_date_array(&refs, 0);
996 assert!(result.is_err());
997 }
998
999 #[test]
1000 fn test_build_date_array_invalid_month_zero() {
1001 let values = vec![json!("2024-00-15")]; let refs = to_refs(&values);
1003 let result = build_date_array(&refs, 0);
1004 assert!(result.is_err());
1005 }
1006
1007 #[test]
1008 fn test_build_date_array_invalid_day_zero() {
1009 let values = vec![json!("2024-01-00")]; let refs = to_refs(&values);
1011 let result = build_date_array(&refs, 0);
1012 assert!(result.is_err());
1013 }
1014
1015 #[test]
1020 fn test_parse_date_to_days_january() {
1021 let days = parse_date_to_days("1970-01-15", 0, 0).unwrap();
1022 assert_eq!(days, 14); }
1024
1025 #[test]
1026 fn test_parse_date_to_days_february() {
1027 let days = parse_date_to_days("1970-02-01", 0, 0).unwrap();
1028 assert_eq!(days, 31); }
1030
1031 #[test]
1032 fn test_parse_date_to_days_march() {
1033 let days = parse_date_to_days("1970-03-01", 0, 0).unwrap();
1034 assert_eq!(days, 59); }
1036
1037 #[test]
1038 fn test_parse_date_to_days_april() {
1039 let days = parse_date_to_days("1970-04-01", 0, 0).unwrap();
1040 assert_eq!(days, 90); }
1042
1043 #[test]
1044 fn test_parse_date_to_days_may() {
1045 let days = parse_date_to_days("1970-05-01", 0, 0).unwrap();
1046 assert_eq!(days, 120); }
1048
1049 #[test]
1050 fn test_parse_date_to_days_june() {
1051 let days = parse_date_to_days("1970-06-01", 0, 0).unwrap();
1052 assert_eq!(days, 151);
1053 }
1054
1055 #[test]
1056 fn test_parse_date_to_days_july() {
1057 let days = parse_date_to_days("1970-07-01", 0, 0).unwrap();
1058 assert_eq!(days, 181);
1059 }
1060
1061 #[test]
1062 fn test_parse_date_to_days_august() {
1063 let days = parse_date_to_days("1970-08-01", 0, 0).unwrap();
1064 assert_eq!(days, 212);
1065 }
1066
1067 #[test]
1068 fn test_parse_date_to_days_september() {
1069 let days = parse_date_to_days("1970-09-01", 0, 0).unwrap();
1070 assert_eq!(days, 243);
1071 }
1072
1073 #[test]
1074 fn test_parse_date_to_days_october() {
1075 let days = parse_date_to_days("1970-10-01", 0, 0).unwrap();
1076 assert_eq!(days, 273);
1077 }
1078
1079 #[test]
1080 fn test_parse_date_to_days_november() {
1081 let days = parse_date_to_days("1970-11-01", 0, 0).unwrap();
1082 assert_eq!(days, 304);
1083 }
1084
1085 #[test]
1086 fn test_parse_date_to_days_december() {
1087 let days = parse_date_to_days("1970-12-01", 0, 0).unwrap();
1088 assert_eq!(days, 334);
1089 }
1090
1091 #[test]
1096 fn test_parse_date_to_days_leap_year_2000() {
1097 let march_1_2000 = parse_date_to_days("2000-03-01", 0, 0).unwrap();
1100 let feb_28_2000 = parse_date_to_days("2000-02-28", 0, 0).unwrap();
1101 assert_eq!(march_1_2000 - feb_28_2000, 2); }
1103
1104 #[test]
1105 fn test_parse_date_to_days_leap_year_2004() {
1106 let march_1_2004 = parse_date_to_days("2004-03-01", 0, 0).unwrap();
1108 let feb_28_2004 = parse_date_to_days("2004-02-28", 0, 0).unwrap();
1109 assert_eq!(march_1_2004 - feb_28_2004, 2); }
1111
1112 #[test]
1113 fn test_parse_date_to_days_non_leap_year_1900() {
1114 let march_1_1900 = parse_date_to_days("1900-03-01", 0, 0).unwrap();
1116 let feb_28_1900 = parse_date_to_days("1900-02-28", 0, 0).unwrap();
1117 assert_eq!(march_1_1900 - feb_28_1900, 1); }
1119
1120 #[test]
1121 fn test_parse_date_to_days_non_leap_year_2023() {
1122 let march_1_2023 = parse_date_to_days("2023-03-01", 0, 0).unwrap();
1124 let feb_28_2023 = parse_date_to_days("2023-02-28", 0, 0).unwrap();
1125 assert_eq!(march_1_2023 - feb_28_2023, 1); }
1127
1128 #[test]
1129 fn test_parse_date_to_days_leap_adjustment_only_after_february() {
1130 let jan_31_2000 = parse_date_to_days("2000-01-31", 0, 0).unwrap();
1132 let jan_30_2000 = parse_date_to_days("2000-01-30", 0, 0).unwrap();
1133 assert_eq!(jan_31_2000 - jan_30_2000, 1); }
1135
1136 #[test]
1137 fn test_parse_date_to_days_before_unix_epoch() {
1138 let days = parse_date_to_days("1969-12-31", 0, 0).unwrap();
1140 assert_eq!(days, -1);
1141 }
1142
1143 #[test]
1144 fn test_parse_date_to_days_far_future() {
1145 let days = parse_date_to_days("2100-01-01", 0, 0).unwrap();
1147 assert!(days > 0);
1148 }
1149
1150 #[test]
1155 fn test_parse_date_to_days_invalid_format_missing_parts() {
1156 let result = parse_date_to_days("2024-01", 0, 0);
1157 assert!(result.is_err());
1158 }
1159
1160 #[test]
1161 fn test_parse_date_to_days_invalid_format_too_many_parts() {
1162 let result = parse_date_to_days("2024-01-15-extra", 0, 0);
1163 assert!(result.is_err());
1164 }
1165
1166 #[test]
1167 fn test_parse_date_to_days_invalid_year() {
1168 let result = parse_date_to_days("XXXX-01-15", 0, 0);
1169 assert!(result.is_err());
1170 }
1171
1172 #[test]
1173 fn test_parse_date_to_days_invalid_month() {
1174 let result = parse_date_to_days("2024-XX-15", 0, 0);
1175 assert!(result.is_err());
1176 }
1177
1178 #[test]
1179 fn test_parse_date_to_days_invalid_day() {
1180 let result = parse_date_to_days("2024-01-XX", 0, 0);
1181 assert!(result.is_err());
1182 }
1183
1184 #[test]
1189 fn test_build_timestamp_array_without_timezone() {
1190 let values = vec![
1191 json!("2024-01-15 10:30:00"),
1192 json!("2024-06-20 14:45:30.123456"),
1193 ];
1194 let refs = to_refs(&values);
1195 let result = build_timestamp_array(&refs, false, 0).unwrap();
1196 assert_eq!(result.len(), 2);
1197 assert_eq!(result.null_count(), 0);
1198 }
1199
1200 #[test]
1201 fn test_build_timestamp_array_with_timezone() {
1202 let values = vec![
1203 json!("2024-01-15 10:30:00"),
1204 json!("2024-06-20 14:45:30.123456"),
1205 ];
1206 let refs = to_refs(&values);
1207 let result = build_timestamp_array(&refs, true, 0).unwrap();
1208 assert_eq!(result.len(), 2);
1209 assert_eq!(result.null_count(), 0);
1210 }
1211
1212 #[test]
1213 fn test_build_timestamp_array_with_null_values() {
1214 let values = vec![
1215 json!("2024-01-15 10:30:00"),
1216 json!(null),
1217 json!("2024-06-20 14:45:30"),
1218 ];
1219 let refs = to_refs(&values);
1220 let result = build_timestamp_array(&refs, false, 0).unwrap();
1221 assert_eq!(result.len(), 3);
1222 assert_eq!(result.null_count(), 1);
1223 }
1224
1225 #[test]
1226 fn test_build_timestamp_array_date_only() {
1227 let values = vec![json!("2024-01-15")];
1229 let refs = to_refs(&values);
1230 let result = build_timestamp_array(&refs, false, 0).unwrap();
1231 assert_eq!(result.len(), 1);
1232 }
1233
1234 #[test]
1235 fn test_build_timestamp_array_invalid_not_string() {
1236 let values = vec![json!(12345)];
1237 let refs = to_refs(&values);
1238 let result = build_timestamp_array(&refs, false, 0);
1239 assert!(result.is_err());
1240 match result.unwrap_err() {
1241 ConversionError::ValueConversionFailed { message, .. } => {
1242 assert!(message.contains("Expected timestamp string"));
1243 }
1244 _ => panic!("Expected ValueConversionFailed"),
1245 }
1246 }
1247
1248 #[test]
1253 fn test_parse_timestamp_to_micros_with_fractional_seconds_3_digits() {
1254 let micros = parse_timestamp_to_micros("1970-01-01 00:00:00.123", 0, 0).unwrap();
1255 assert_eq!(micros, 123_000);
1256 }
1257
1258 #[test]
1259 fn test_parse_timestamp_to_micros_with_fractional_seconds_6_digits() {
1260 let micros = parse_timestamp_to_micros("1970-01-01 00:00:00.123456", 0, 0).unwrap();
1261 assert_eq!(micros, 123_456);
1262 }
1263
1264 #[test]
1265 fn test_parse_timestamp_to_micros_with_fractional_seconds_9_digits() {
1266 let micros = parse_timestamp_to_micros("1970-01-01 00:00:00.123456789", 0, 0).unwrap();
1268 assert_eq!(micros, 123_456);
1269 }
1270
1271 #[test]
1272 fn test_parse_timestamp_to_micros_with_fractional_seconds_1_digit() {
1273 let micros = parse_timestamp_to_micros("1970-01-01 00:00:00.1", 0, 0).unwrap();
1274 assert_eq!(micros, 100_000);
1275 }
1276
1277 #[test]
1278 fn test_parse_timestamp_to_micros_with_fractional_seconds_2_digits() {
1279 let micros = parse_timestamp_to_micros("1970-01-01 00:00:00.12", 0, 0).unwrap();
1280 assert_eq!(micros, 120_000);
1281 }
1282
1283 #[test]
1284 fn test_parse_timestamp_to_micros_hours_minutes_only() {
1285 let micros = parse_timestamp_to_micros("1970-01-01 12:30", 0, 0).unwrap();
1286 assert_eq!(micros, 12 * 3600 * 1_000_000 + 30 * 60 * 1_000_000);
1287 }
1288
1289 #[test]
1290 fn test_parse_timestamp_to_micros_full_time() {
1291 let micros = parse_timestamp_to_micros("1970-01-01 12:30:45", 0, 0).unwrap();
1292 assert_eq!(
1293 micros,
1294 12 * 3600 * 1_000_000 + 30 * 60 * 1_000_000 + 45 * 1_000_000
1295 );
1296 }
1297
1298 #[test]
1299 fn test_parse_timestamp_to_micros_empty_string() {
1300 let result = parse_timestamp_to_micros("", 0, 0);
1301 assert!(result.is_err());
1302 }
1303
1304 #[test]
1305 fn test_parse_timestamp_to_micros_invalid_hour() {
1306 let result = parse_timestamp_to_micros("1970-01-01 XX:30:00", 0, 0);
1307 assert!(result.is_err());
1308 }
1309
1310 #[test]
1311 fn test_parse_timestamp_to_micros_invalid_minute() {
1312 let result = parse_timestamp_to_micros("1970-01-01 12:XX:00", 0, 0);
1313 assert!(result.is_err());
1314 }
1315
1316 #[test]
1317 fn test_parse_timestamp_to_micros_invalid_second() {
1318 let result = parse_timestamp_to_micros("1970-01-01 12:30:XX", 0, 0);
1319 assert!(result.is_err());
1320 }
1321
1322 #[test]
1327 fn test_build_interval_year_to_month_array_positive() {
1328 let values = vec![json!("+01-06"), json!("+00-03")];
1329 let refs = to_refs(&values);
1330 let result = build_interval_year_to_month_array(&refs, 0).unwrap();
1331 assert_eq!(result.len(), 2);
1332 assert_eq!(result.null_count(), 0);
1333 }
1334
1335 #[test]
1336 fn test_build_interval_year_to_month_array_negative() {
1337 let values = vec![json!("-02-03"), json!("-00-11")];
1338 let refs = to_refs(&values);
1339 let result = build_interval_year_to_month_array(&refs, 0).unwrap();
1340 assert_eq!(result.len(), 2);
1341 assert_eq!(result.null_count(), 0);
1342 }
1343
1344 #[test]
1345 fn test_build_interval_year_to_month_array_with_nulls() {
1346 let values = vec![json!("+01-06"), json!(null), json!("-02-03")];
1347 let refs = to_refs(&values);
1348 let result = build_interval_year_to_month_array(&refs, 0).unwrap();
1349 assert_eq!(result.len(), 3);
1350 assert_eq!(result.null_count(), 1);
1351 }
1352
1353 #[test]
1354 fn test_build_interval_year_to_month_array_invalid_not_string() {
1355 let values = vec![json!(12345)];
1356 let refs = to_refs(&values);
1357 let result = build_interval_year_to_month_array(&refs, 0);
1358 assert!(result.is_err());
1359 match result.unwrap_err() {
1360 ConversionError::ValueConversionFailed { message, .. } => {
1361 assert!(message.contains("Expected interval string"));
1362 }
1363 _ => panic!("Expected ValueConversionFailed"),
1364 }
1365 }
1366
1367 #[test]
1372 fn test_parse_interval_year_to_month_zero_years() {
1373 let months = parse_interval_year_to_month("+00-06", 0, 0).unwrap();
1374 assert_eq!(months, 6);
1375 }
1376
1377 #[test]
1378 fn test_parse_interval_year_to_month_zero_months() {
1379 let months = parse_interval_year_to_month("+05-00", 0, 0).unwrap();
1380 assert_eq!(months, 60);
1381 }
1382
1383 #[test]
1384 fn test_parse_interval_year_to_month_large_value() {
1385 let months = parse_interval_year_to_month("+99-11", 0, 0).unwrap();
1386 assert_eq!(months, 99 * 12 + 11);
1387 }
1388
1389 #[test]
1390 fn test_parse_interval_year_to_month_negative_large_value() {
1391 let months = parse_interval_year_to_month("-99-11", 0, 0).unwrap();
1392 assert_eq!(months, -(99 * 12 + 11));
1393 }
1394
1395 #[test]
1396 fn test_parse_interval_year_to_month_invalid_format() {
1397 let result = parse_interval_year_to_month("01-06", 0, 0); assert!(result.is_ok());
1400 }
1401
1402 #[test]
1403 fn test_parse_interval_year_to_month_invalid_format_missing_parts() {
1404 let result = parse_interval_year_to_month("+01", 0, 0);
1405 assert!(result.is_err());
1406 }
1407
1408 #[test]
1409 fn test_parse_interval_year_to_month_invalid_years() {
1410 let result = parse_interval_year_to_month("+XX-06", 0, 0);
1411 assert!(result.is_err());
1412 }
1413
1414 #[test]
1415 fn test_parse_interval_year_to_month_invalid_months() {
1416 let result = parse_interval_year_to_month("+01-XX", 0, 0);
1417 assert!(result.is_err());
1418 }
1419
1420 #[test]
1425 fn test_build_interval_day_to_second_array_with_fractional_seconds() {
1426 let values = vec![json!("+01 12:30:45.123456789")];
1427 let refs = to_refs(&values);
1428 let result = build_interval_day_to_second_array(&refs, 0).unwrap();
1429 assert_eq!(result.len(), 1);
1430 assert_eq!(result.null_count(), 0);
1431 }
1432
1433 #[test]
1434 fn test_build_interval_day_to_second_array_without_fractional_seconds() {
1435 let values = vec![json!("+01 12:30:45")];
1436 let refs = to_refs(&values);
1437 let result = build_interval_day_to_second_array(&refs, 0).unwrap();
1438 assert_eq!(result.len(), 1);
1439 assert_eq!(result.null_count(), 0);
1440 }
1441
1442 #[test]
1443 fn test_build_interval_day_to_second_array_negative() {
1444 let values = vec![json!("-02 08:15:30.500000000")];
1445 let refs = to_refs(&values);
1446 let result = build_interval_day_to_second_array(&refs, 0).unwrap();
1447 assert_eq!(result.len(), 1);
1448 assert_eq!(result.null_count(), 0);
1449 }
1450
1451 #[test]
1452 fn test_build_interval_day_to_second_array_with_nulls() {
1453 let values = vec![json!("+01 12:30:45"), json!(null), json!("-02 08:15:30")];
1454 let refs = to_refs(&values);
1455 let result = build_interval_day_to_second_array(&refs, 0).unwrap();
1456 assert_eq!(result.len(), 3);
1457 assert_eq!(result.null_count(), 1);
1458 }
1459
1460 #[test]
1461 fn test_build_interval_day_to_second_array_invalid_not_string() {
1462 let values = vec![json!(12345)];
1463 let refs = to_refs(&values);
1464 let result = build_interval_day_to_second_array(&refs, 0);
1465 assert!(result.is_err());
1466 match result.unwrap_err() {
1467 ConversionError::ValueConversionFailed { message, .. } => {
1468 assert!(message.contains("Expected interval string"));
1469 }
1470 _ => panic!("Expected ValueConversionFailed"),
1471 }
1472 }
1473
1474 #[test]
1479 fn test_parse_interval_day_to_second_days_only() {
1480 let (days, nanos) = parse_interval_day_to_second("+05", 0, 0).unwrap();
1481 assert_eq!(days, 5);
1482 assert_eq!(nanos, 0);
1483 }
1484
1485 #[test]
1486 fn test_parse_interval_day_to_second_hours_minutes_only() {
1487 let (days, nanos) = parse_interval_day_to_second("+01 12:30", 0, 0).unwrap();
1488 assert_eq!(days, 1);
1489 assert_eq!(nanos, 12 * 3600 * 1_000_000_000 + 30 * 60 * 1_000_000_000);
1490 }
1491
1492 #[test]
1493 fn test_parse_interval_day_to_second_negative_values() {
1494 let (days, nanos) = parse_interval_day_to_second("-03 06:15:30", 0, 0).unwrap();
1495 assert_eq!(days, -3);
1496 assert_eq!(
1497 nanos,
1498 -(6 * 3600 * 1_000_000_000 + 15 * 60 * 1_000_000_000 + 30 * 1_000_000_000)
1499 );
1500 }
1501
1502 #[test]
1503 fn test_parse_interval_day_to_second_with_fractional_3_digits() {
1504 let (days, nanos) = parse_interval_day_to_second("+00 00:00:00.123", 0, 0).unwrap();
1505 assert_eq!(days, 0);
1506 assert_eq!(nanos, 123_000_000);
1507 }
1508
1509 #[test]
1510 fn test_parse_interval_day_to_second_with_fractional_6_digits() {
1511 let (days, nanos) = parse_interval_day_to_second("+00 00:00:00.123456", 0, 0).unwrap();
1512 assert_eq!(days, 0);
1513 assert_eq!(nanos, 123_456_000);
1514 }
1515
1516 #[test]
1517 fn test_parse_interval_day_to_second_with_fractional_9_digits() {
1518 let (days, nanos) = parse_interval_day_to_second("+00 00:00:00.123456789", 0, 0).unwrap();
1519 assert_eq!(days, 0);
1520 assert_eq!(nanos, 123_456_789);
1521 }
1522
1523 #[test]
1524 fn test_parse_interval_day_to_second_with_fractional_12_digits() {
1525 let (days, nanos) =
1527 parse_interval_day_to_second("+00 00:00:00.123456789012", 0, 0).unwrap();
1528 assert_eq!(days, 0);
1529 assert_eq!(nanos, 123_456_789);
1530 }
1531
1532 #[test]
1533 fn test_parse_interval_day_to_second_empty_string() {
1534 let result = parse_interval_day_to_second("", 0, 0);
1535 assert!(result.is_err());
1536 }
1537
1538 #[test]
1539 fn test_parse_interval_day_to_second_invalid_days() {
1540 let result = parse_interval_day_to_second("+XX 12:30:45", 0, 0);
1541 assert!(result.is_err());
1542 }
1543
1544 #[test]
1545 fn test_parse_interval_day_to_second_invalid_hours() {
1546 let result = parse_interval_day_to_second("+01 XX:30:45", 0, 0);
1547 assert!(result.is_err());
1548 }
1549
1550 #[test]
1551 fn test_parse_interval_day_to_second_invalid_minutes() {
1552 let result = parse_interval_day_to_second("+01 12:XX:45", 0, 0);
1553 assert!(result.is_err());
1554 }
1555
1556 #[test]
1557 fn test_parse_interval_day_to_second_invalid_seconds() {
1558 let result = parse_interval_day_to_second("+01 12:30:XX", 0, 0);
1559 assert!(result.is_err());
1560 }
1561
1562 #[test]
1567 fn test_build_binary_array_valid_hex() {
1568 let values = vec![json!("48656c6c6f"), json!("576f726c64")];
1569 let refs = to_refs(&values);
1570 let result = build_binary_array(&refs, 0).unwrap();
1571 assert_eq!(result.len(), 2);
1572 assert_eq!(result.null_count(), 0);
1573 }
1574
1575 #[test]
1576 fn test_build_binary_array_with_null_values() {
1577 let values = vec![json!("48656c6c6f"), json!(null), json!("576f726c64")];
1578 let refs = to_refs(&values);
1579 let result = build_binary_array(&refs, 0).unwrap();
1580 assert_eq!(result.len(), 3);
1581 assert_eq!(result.null_count(), 1);
1582 }
1583
1584 #[test]
1585 fn test_build_binary_array_empty_hex() {
1586 let values = vec![json!("")];
1587 let refs = to_refs(&values);
1588 let result = build_binary_array(&refs, 0).unwrap();
1589 assert_eq!(result.len(), 1);
1590 assert_eq!(result.null_count(), 0);
1591 }
1592
1593 #[test]
1594 fn test_build_binary_array_invalid_not_string() {
1595 let values = vec![json!(12345)];
1596 let refs = to_refs(&values);
1597 let result = build_binary_array(&refs, 0);
1598 assert!(result.is_err());
1599 match result.unwrap_err() {
1600 ConversionError::ValueConversionFailed { message, .. } => {
1601 assert!(message.contains("Expected hex string"));
1602 }
1603 _ => panic!("Expected ValueConversionFailed"),
1604 }
1605 }
1606
1607 #[test]
1608 fn test_build_binary_array_invalid_hex_odd_length() {
1609 let values = vec![json!("abc")]; let refs = to_refs(&values);
1611 let result = build_binary_array(&refs, 0);
1612 assert!(result.is_err());
1613 }
1614
1615 #[test]
1616 fn test_build_binary_array_invalid_hex_chars() {
1617 let values = vec![json!("ghij")]; let refs = to_refs(&values);
1619 let result = build_binary_array(&refs, 0);
1620 assert!(result.is_err());
1621 }
1622
1623 #[test]
1624 fn test_build_binary_array_capacity_estimation_with_samples() {
1625 let values: Vec<Value> = (0..15).map(|_| json!("deadbeef")).collect();
1627 let refs = to_refs(&values);
1628 let result = build_binary_array(&refs, 0).unwrap();
1629 assert_eq!(result.len(), 15);
1630 }
1631
1632 #[test]
1633 fn test_build_binary_array_capacity_estimation_all_nulls() {
1634 let values: Vec<Value> = (0..5).map(|_| json!(null)).collect();
1636 let refs = to_refs(&values);
1637 let result = build_binary_array(&refs, 0).unwrap();
1638 assert_eq!(result.len(), 5);
1639 assert_eq!(result.null_count(), 5);
1640 }
1641
1642 #[test]
1643 fn test_build_double_array_from_integer() {
1644 let values = vec![json!(42), json!(100)];
1645 let refs = to_refs(&values);
1646 let result = build_double_array(&refs, 0).unwrap();
1647 assert_eq!(result.len(), 2);
1648 }
1649
1650 #[test]
1651 fn test_build_double_array_from_string_numeric() {
1652 let values = vec![json!("3.14159")];
1653 let refs = to_refs(&values);
1654 let result = build_double_array(&refs, 0).unwrap();
1655 assert_eq!(result.len(), 1);
1656 }
1657
1658 #[test]
1659 fn test_build_double_array_neg_infinity() {
1660 let values = vec![json!("-Infinity")];
1661 let refs = to_refs(&values);
1662 let result = build_double_array(&refs, 0).unwrap();
1663 assert_eq!(result.len(), 1);
1664 }
1665
1666 #[test]
1667 fn test_build_double_array_nan() {
1668 let values = vec![json!("NaN")];
1669 let refs = to_refs(&values);
1670 let result = build_double_array(&refs, 0).unwrap();
1671 assert_eq!(result.len(), 1);
1672 }
1673
1674 #[test]
1675 fn test_build_double_array_invalid_string() {
1676 let values = vec![json!("not a number")];
1677 let refs = to_refs(&values);
1678 let result = build_double_array(&refs, 0);
1679 assert!(result.is_err());
1680 }
1681
1682 #[test]
1683 fn test_parse_decimal_to_i128_from_float() {
1684 let result = parse_decimal_to_i128(&json!(123.45), 10, 2, 0, 0).unwrap();
1685 assert_eq!(result, 12345);
1686 }
1687
1688 #[test]
1689 fn test_parse_decimal_to_i128_invalid_decimal_format() {
1690 let result = parse_decimal_to_i128(&json!("1.2.3"), 10, 2, 0, 0);
1691 assert!(result.is_err());
1692 }
1693
1694 #[test]
1695 fn test_parse_decimal_to_i128_invalid_integer_part() {
1696 let result = parse_decimal_to_i128(&json!("abc.45"), 10, 2, 0, 0);
1697 assert!(result.is_err());
1698 }
1699
1700 #[test]
1701 fn test_parse_decimal_to_i128_invalid_decimal_part() {
1702 let result = parse_decimal_to_i128(&json!("123.xyz"), 10, 2, 0, 0);
1703 assert!(result.is_err());
1704 }
1705
1706 #[test]
1707 fn test_parse_decimal_to_i128_non_numeric_value() {
1708 let result = parse_decimal_to_i128(&json!({"key": "value"}), 10, 2, 0, 0);
1709 assert!(result.is_err());
1710 }
1711
1712 #[test]
1713 fn test_decode_hex_uppercase() {
1714 let bytes = decode_hex("DEADBEEF").unwrap();
1715 assert_eq!(bytes, vec![0xDE, 0xAD, 0xBE, 0xEF]);
1716 }
1717
1718 #[test]
1719 fn test_decode_hex_mixed_case() {
1720 let bytes = decode_hex("DeAdBeEf").unwrap();
1721 assert_eq!(bytes, vec![0xDE, 0xAD, 0xBE, 0xEF]);
1722 }
1723}