1use std::{convert, sync::Arc};
2
3use super::{Error, Result, Statement};
4use crate::core::LogicalTypeId;
5use crate::types::{self, Decimal, EnumType, FromSql, FromSqlError, ListType, ValueRef};
6
7use arrow::{
8 array::{
9 self, Array, ArrayRef, DictionaryArray, FixedSizeBinaryArray, FixedSizeListArray, ListArray, MapArray,
10 StructArray,
11 },
12 datatypes::*,
13};
14use fallible_iterator::FallibleIterator;
15use fallible_streaming_iterator::FallibleStreamingIterator;
16
17#[must_use = "Rows is lazy and will do nothing unless consumed"]
19pub struct Rows<'stmt> {
20 pub(crate) stmt: Option<&'stmt Statement<'stmt>>,
21 arr: Arc<Option<StructArray>>,
22 row: Option<Row<'stmt>>,
23 current_batch_row: usize,
24}
25
26impl<'stmt> Rows<'stmt> {
27 #[inline]
28 fn reset(&mut self) {
29 self.current_batch_row = 0;
30 self.arr = Arc::new(None);
31 }
32
33 #[allow(clippy::should_implement_trait)] #[inline]
47 pub fn next(&mut self) -> Result<Option<&Row<'stmt>>> {
48 self.advance()?;
49 Ok((*self).get())
50 }
51
52 #[inline]
53 fn batch_row_count(&self) -> usize {
54 if self.arr.is_none() {
55 return 0;
56 }
57 self.arr.as_ref().as_ref().unwrap().len()
58 }
59
60 #[inline]
77 pub fn map<F, B>(self, f: F) -> Map<'stmt, F>
78 where
79 F: FnMut(&Row<'_>) -> Result<B>,
80 {
81 Map { rows: self, f }
82 }
83
84 #[inline]
87 pub fn mapped<F, B>(self, f: F) -> MappedRows<'stmt, F>
88 where
89 F: FnMut(&Row<'_>) -> Result<B>,
90 {
91 MappedRows { rows: self, map: f }
92 }
93
94 #[inline]
98 pub fn and_then<F, T, E>(self, f: F) -> AndThenRows<'stmt, F>
99 where
100 F: FnMut(&Row<'_>) -> Result<T, E>,
101 {
102 AndThenRows { rows: self, map: f }
103 }
104
105 pub fn as_ref(&self) -> Option<&Statement<'stmt>> {
129 self.stmt
130 }
131}
132
133impl<'stmt> Rows<'stmt> {
134 #[inline]
135 pub(crate) fn new(stmt: &'stmt Statement<'stmt>) -> Self {
136 Rows {
137 stmt: Some(stmt),
138 arr: Arc::new(None),
139 row: None,
140 current_batch_row: 0,
141 }
142 }
143
144 #[inline]
145 pub(crate) fn get_expected_row(&mut self) -> Result<&Row<'stmt>> {
146 match self.next()? {
147 Some(row) => Ok(row),
148 None => Err(Error::QueryReturnedNoRows),
149 }
150 }
151}
152
153#[must_use = "iterators are lazy and do nothing unless consumed"]
156pub struct Map<'stmt, F> {
157 rows: Rows<'stmt>,
158 f: F,
159}
160
161impl<F, B> FallibleIterator for Map<'_, F>
162where
163 F: FnMut(&Row<'_>) -> Result<B>,
164{
165 type Error = Error;
166 type Item = B;
167
168 #[inline]
169 fn next(&mut self) -> Result<Option<B>> {
170 match self.rows.next()? {
171 Some(v) => Ok(Some((self.f)(v)?)),
172 None => Ok(None),
173 }
174 }
175}
176
177#[must_use = "iterators are lazy and do nothing unless consumed"]
182pub struct MappedRows<'stmt, F> {
183 rows: Rows<'stmt>,
184 map: F,
185}
186
187impl<T, F> Iterator for MappedRows<'_, F>
188where
189 F: FnMut(&Row<'_>) -> Result<T>,
190{
191 type Item = Result<T>;
192
193 #[inline]
194 fn next(&mut self) -> Option<Result<T>> {
195 let map = &mut self.map;
196 self.rows.next().transpose().map(|row_result| row_result.and_then(map))
197 }
198}
199
200#[must_use = "iterators are lazy and do nothing unless consumed"]
203pub struct AndThenRows<'stmt, F> {
204 rows: Rows<'stmt>,
205 map: F,
206}
207
208impl<T, E, F> Iterator for AndThenRows<'_, F>
209where
210 E: convert::From<Error>,
211 F: FnMut(&Row<'_>) -> Result<T, E>,
212{
213 type Item = Result<T, E>;
214
215 #[inline]
216 fn next(&mut self) -> Option<Self::Item> {
217 let map = &mut self.map;
218 self.rows
219 .next()
220 .transpose()
221 .map(|row_result| row_result.map_err(E::from).and_then(map))
222 }
223}
224
225impl<'stmt> FallibleStreamingIterator for Rows<'stmt> {
244 type Error = Error;
245 type Item = Row<'stmt>;
246
247 #[inline]
248 fn advance(&mut self) -> Result<()> {
249 match self.stmt {
250 Some(stmt) => {
251 while self.current_batch_row >= self.batch_row_count() {
252 self.arr = Arc::new(stmt.step()?);
253 if self.arr.is_none() {
254 self.reset();
255 self.row = None;
256 return Ok(());
257 }
258 self.current_batch_row = 0;
259 }
260
261 self.row = Some(Row {
262 stmt,
263 arr: self.arr.clone(),
264 current_row: self.current_batch_row,
265 });
266 self.current_batch_row += 1;
267 Ok(())
268 }
269 None => {
270 self.row = None;
271 Ok(())
272 }
273 }
274 }
275
276 #[inline]
277 fn get(&self) -> Option<&Row<'stmt>> {
278 self.row.as_ref()
279 }
280}
281
282pub struct Row<'stmt> {
284 pub(crate) stmt: &'stmt Statement<'stmt>,
285 arr: Arc<Option<StructArray>>,
286 current_row: usize,
287}
288
289fn decimal_value_ref(width: u8, scale: i8, value: i128) -> ValueRef<'static> {
290 let scale = Decimal::validate_signed_scale(width, scale)
291 .unwrap_or_else(|err| panic!("Invalid Arrow decimal metadata for width {width} scale {scale}: {err}"));
292 ValueRef::Decimal(Decimal::from_chunk(width, scale, value))
293}
294
295#[allow(clippy::needless_lifetimes)]
296impl<'stmt> Row<'stmt> {
297 pub fn get_unwrap<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
310 self.get(idx).unwrap()
311 }
312
313 pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
330 let idx = idx.idx(self.stmt)?;
331 let value = self.value_ref(self.current_row, idx);
332 FromSql::column_result(value).map_err(|err| match err {
333 FromSqlError::InvalidType => {
334 Error::InvalidColumnType(idx, self.stmt.column_name_unwrap(idx).into(), value.data_type())
335 }
336 FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
337 FromSqlError::OutOfRangeUnsigned(i) => Error::UnsignedIntegralValueOutOfRange(idx, i),
338 FromSqlError::Other(err) => Error::FromSqlConversionFailure(idx, value.data_type(), err),
339 #[cfg(feature = "uuid")]
340 FromSqlError::InvalidUuidSize(_) => {
341 Error::InvalidColumnType(idx, self.stmt.column_name_unwrap(idx).into(), value.data_type())
342 }
343 })
344 }
345
346 pub fn get_ref<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'_>> {
362 let idx = idx.idx(self.stmt)?;
363 let val_ref = self.value_ref(self.current_row, idx);
367 Ok(val_ref)
368 }
369
370 fn value_ref(&self, row: usize, col: usize) -> ValueRef<'_> {
371 let column = self.arr.as_ref().as_ref().unwrap().column(col);
372 let value = Self::value_ref_internal(row, column);
373
374 match value {
377 ValueRef::Blob(bytes) => match self.stmt.result_column_logical_id(col) {
378 Some(LogicalTypeId::Geometry) => ValueRef::Geometry(bytes),
379 _ => ValueRef::Blob(bytes),
380 },
381 ValueRef::HugeInt(value) => match self.stmt.result_column_logical_id(col) {
388 Some(LogicalTypeId::UHugeint) => ValueRef::UHugeInt(value as u128),
389 Some(LogicalTypeId::Decimal) => {
390 if let DataType::Decimal128(width, 0) = column.data_type() {
391 decimal_value_ref(*width, 0, value)
392 } else {
393 ValueRef::HugeInt(value)
394 }
395 }
396 _ => ValueRef::HugeInt(value),
397 },
398 value => value,
399 }
400 }
401
402 pub(crate) fn value_ref_internal<'a>(row: usize, column: &'a ArrayRef) -> ValueRef<'a> {
403 if column.is_null(row) {
404 return ValueRef::Null;
405 }
406 match column.data_type() {
409 DataType::Utf8 => {
410 let array = column.as_any().downcast_ref::<array::StringArray>().unwrap();
411 ValueRef::from(array.value(row))
412 }
413 DataType::LargeUtf8 => {
414 let array = column.as_any().downcast_ref::<array::LargeStringArray>().unwrap();
415 ValueRef::from(array.value(row))
416 }
417 DataType::Binary => {
418 let array = column.as_any().downcast_ref::<array::BinaryArray>().unwrap();
419 ValueRef::Blob(array.value(row))
420 }
421 DataType::LargeBinary => {
422 let array = column.as_any().downcast_ref::<array::LargeBinaryArray>().unwrap();
423 ValueRef::Blob(array.value(row))
424 }
425 DataType::FixedSizeBinary(_) => {
426 let array = column.as_any().downcast_ref::<FixedSizeBinaryArray>().unwrap();
427 ValueRef::Blob(array.value(row))
428 }
429 DataType::Boolean => {
430 let array = column.as_any().downcast_ref::<array::BooleanArray>().unwrap();
431 ValueRef::Boolean(array.value(row))
432 }
433 DataType::Int8 => {
434 let array = column.as_any().downcast_ref::<array::Int8Array>().unwrap();
435 ValueRef::TinyInt(array.value(row))
436 }
437 DataType::Int16 => {
438 let array = column.as_any().downcast_ref::<array::Int16Array>().unwrap();
439 ValueRef::SmallInt(array.value(row))
440 }
441 DataType::Int32 => {
442 let array = column.as_any().downcast_ref::<array::Int32Array>().unwrap();
443 ValueRef::Int(array.value(row))
444 }
445 DataType::Int64 => {
446 let array = column.as_any().downcast_ref::<array::Int64Array>().unwrap();
447 ValueRef::BigInt(array.value(row))
448 }
449 DataType::UInt8 => {
450 let array = column.as_any().downcast_ref::<array::UInt8Array>().unwrap();
451 ValueRef::UTinyInt(array.value(row))
452 }
453 DataType::UInt16 => {
454 let array = column.as_any().downcast_ref::<array::UInt16Array>().unwrap();
455 ValueRef::USmallInt(array.value(row))
456 }
457 DataType::UInt32 => {
458 let array = column.as_any().downcast_ref::<array::UInt32Array>().unwrap();
459 ValueRef::UInt(array.value(row))
460 }
461 DataType::UInt64 => {
462 let array = column.as_any().downcast_ref::<array::UInt64Array>().unwrap();
463 ValueRef::UBigInt(array.value(row))
464 }
465 DataType::Float16 => {
466 let array = column.as_any().downcast_ref::<array::Float32Array>().unwrap();
467 ValueRef::Float(array.value(row))
468 }
469 DataType::Float32 => {
470 let array = column.as_any().downcast_ref::<array::Float32Array>().unwrap();
471 ValueRef::Float(array.value(row))
472 }
473 DataType::Float64 => {
474 let array = column.as_any().downcast_ref::<array::Float64Array>().unwrap();
475 ValueRef::Double(array.value(row))
476 }
477 DataType::Decimal32(width, scale) => {
478 let array = column.as_any().downcast_ref::<array::Decimal32Array>().unwrap();
479 let value = i128::from(array.value(row));
480 decimal_value_ref(*width, *scale, value)
481 }
482 DataType::Decimal64(width, scale) => {
483 let array = column.as_any().downcast_ref::<array::Decimal64Array>().unwrap();
484 let value = i128::from(array.value(row));
485 decimal_value_ref(*width, *scale, value)
486 }
487 DataType::Decimal128(width, scale) => {
488 let array = column.as_any().downcast_ref::<array::Decimal128Array>().unwrap();
489 let value = array.value(row);
490 if *scale == 0 && *width == Decimal::MAX_WIDTH {
491 ValueRef::HugeInt(value)
492 } else {
493 decimal_value_ref(*width, *scale, value)
494 }
495 }
496 DataType::Timestamp(unit, _) if *unit == TimeUnit::Second => {
497 let array = column.as_any().downcast_ref::<array::TimestampSecondArray>().unwrap();
498 ValueRef::Timestamp(types::TimeUnit::Second, array.value(row))
499 }
500 DataType::Timestamp(unit, _) if *unit == TimeUnit::Millisecond => {
501 let array = column
502 .as_any()
503 .downcast_ref::<array::TimestampMillisecondArray>()
504 .unwrap();
505 ValueRef::Timestamp(types::TimeUnit::Millisecond, array.value(row))
506 }
507 DataType::Timestamp(unit, _) if *unit == TimeUnit::Microsecond => {
508 let array = column
509 .as_any()
510 .downcast_ref::<array::TimestampMicrosecondArray>()
511 .unwrap();
512 ValueRef::Timestamp(types::TimeUnit::Microsecond, array.value(row))
513 }
514 DataType::Timestamp(unit, _) if *unit == TimeUnit::Nanosecond => {
515 let array = column
516 .as_any()
517 .downcast_ref::<array::TimestampNanosecondArray>()
518 .unwrap();
519 ValueRef::Timestamp(types::TimeUnit::Nanosecond, array.value(row))
520 }
521 DataType::Date32 => {
522 let array = column.as_any().downcast_ref::<array::Date32Array>().unwrap();
523 ValueRef::Date32(array.value(row))
524 }
525 DataType::Time64(TimeUnit::Microsecond) => {
526 let array = column.as_any().downcast_ref::<array::Time64MicrosecondArray>().unwrap();
527 ValueRef::Time64(types::TimeUnit::Microsecond, array.value(row))
528 }
529 DataType::Interval(unit) => match unit {
530 IntervalUnit::MonthDayNano => {
531 let array = column
532 .as_any()
533 .downcast_ref::<array::IntervalMonthDayNanoArray>()
534 .unwrap();
535 let value = array.value(row);
536
537 ValueRef::Interval {
538 months: value.months,
539 days: value.days,
540 nanos: value.nanoseconds,
541 }
542 }
543 _ => unimplemented!("{:?}", unit),
544 },
545 DataType::LargeList(..) => {
558 let arr = column.as_any().downcast_ref::<array::LargeListArray>().unwrap();
559
560 ValueRef::List(ListType::Large(arr), row)
561 }
562 DataType::List(..) => {
563 let arr = column.as_any().downcast_ref::<ListArray>().unwrap();
564
565 ValueRef::List(ListType::Regular(arr), row)
566 }
567 DataType::Dictionary(key_type, ..) => {
568 let column = column.as_any();
569 ValueRef::Enum(
570 match key_type.as_ref() {
571 DataType::UInt8 => {
572 EnumType::UInt8(column.downcast_ref::<DictionaryArray<UInt8Type>>().unwrap())
573 }
574 DataType::UInt16 => {
575 EnumType::UInt16(column.downcast_ref::<DictionaryArray<UInt16Type>>().unwrap())
576 }
577 DataType::UInt32 => {
578 EnumType::UInt32(column.downcast_ref::<DictionaryArray<UInt32Type>>().unwrap())
579 }
580 typ => panic!("Unsupported key type: {typ:?}"),
581 },
582 row,
583 )
584 }
585 DataType::Struct(_) => {
586 let res = column.as_any().downcast_ref::<StructArray>().unwrap();
587 ValueRef::Struct(res, row)
588 }
589 DataType::Map(..) => {
590 let arr = column.as_any().downcast_ref::<MapArray>().unwrap();
591 ValueRef::Map(arr, row)
592 }
593 DataType::FixedSizeList(..) => {
594 let arr = column.as_any().downcast_ref::<FixedSizeListArray>().unwrap();
595 ValueRef::Array(arr, row)
596 }
597 DataType::Union(..) => ValueRef::Union(column, row),
598 _ => unreachable!("invalid value: {}", column.data_type()),
599 }
600 }
601
602 pub fn get_ref_unwrap<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
618 self.get_ref(idx).unwrap()
619 }
620}
621
622impl<'stmt> AsRef<Statement<'stmt>> for Row<'stmt> {
623 fn as_ref(&self) -> &Statement<'stmt> {
624 self.stmt
625 }
626}
627
628mod sealed {
629 pub trait Sealed {}
632 impl Sealed for usize {}
633 impl Sealed for &str {}
634}
635
636pub trait RowIndex: sealed::Sealed {
640 fn idx(&self, stmt: &Statement<'_>) -> Result<usize>;
643}
644
645impl RowIndex for usize {
646 #[inline]
647 fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
648 if *self >= stmt.column_count() {
649 Err(Error::InvalidColumnIndex(*self))
650 } else {
651 Ok(*self)
652 }
653 }
654}
655
656impl RowIndex for &'_ str {
657 #[inline]
658 fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
659 stmt.column_index(self)
660 }
661}
662
663macro_rules! tuple_try_from_row {
664 () => {
665 impl<'a> convert::TryFrom<&'a Row<'a>> for () {
666 type Error = crate::Error;
667
668 fn try_from(_: &'a Row<'a>) -> Result<Self> {
669 Ok(())
670 }
671 }
672 };
673 ($($field:ident),+) => {
674 impl<'a, $($field,)*> convert::TryFrom<&'a Row<'a>> for ($($field,)*) where $($field: FromSql,)* {
675 type Error = crate::Error;
676
677 fn try_from(row: &'a Row<'a>) -> Result<Self> {
678 let mut index = 0;
679 let values = (
680 $({
681 let value = row.get::<_, $field>(index)?;
682 index += 1;
683 value
684 },)*
685 );
686 let _ = index;
688 Ok(values)
689 }
690 }
691 }
692}
693
694macro_rules! tuples_try_from_row {
695 () => {
696 tuple_try_from_row!();
698 };
699 ($first:ident $(, $remaining:ident)*) => {
700 tuple_try_from_row!($first $(, $remaining)*);
701 tuples_try_from_row!($($remaining),*);
702 };
703}
704
705tuples_try_from_row!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
706
707#[cfg(test)]
708mod tests {
709 use crate::{
710 Connection, Error, Result,
711 types::{Decimal, Type, Value, ValueRef},
712 };
713
714 const U128_MAX_SQL: &str = "340282366920938463463374607431768211455";
715 const I128_MAX_PLUS_ONE_SQL: &str = "170141183460469231731687303715884105728";
716 const WIDE_DECIMAL_SQL: &str = "123456789012345678901234567890.12";
717 const WIDE_DECIMAL_MANTISSA: i128 = 12_345_678_901_234_567_890_123_456_789_012;
718
719 #[test]
720 fn test_try_from_row_for_tuple_0() -> Result<()> {
721 use std::convert::TryFrom;
722
723 let conn = Connection::open_in_memory()?;
724 conn.query_row("SELECT 1", [], |row| <()>::try_from(row))?;
725 Ok(())
726 }
727
728 #[test]
729 fn test_try_from_row_for_tuple_1() -> Result<()> {
730 use crate::ToSql;
731 use std::convert::TryFrom;
732
733 let conn = Connection::open_in_memory()?;
734 conn.execute(
735 "CREATE TABLE test (a INTEGER)",
736 crate::params_from_iter(std::iter::empty::<&dyn ToSql>()),
737 )?;
738 conn.execute("INSERT INTO test VALUES (42)", [])?;
739 let val = conn.query_row("SELECT a FROM test", [], |row| <(u32,)>::try_from(row))?;
740 assert_eq!(val, (42,));
741 let fail = conn.query_row("SELECT a FROM test", [], |row| <(u32, u32)>::try_from(row));
742 assert!(fail.is_err());
743 Ok(())
744 }
745
746 #[test]
747 fn test_try_from_row_for_tuple_2() -> Result<()> {
748 use std::convert::TryFrom;
749
750 let conn = Connection::open_in_memory()?;
751 conn.execute("CREATE TABLE test (a INTEGER, b INTEGER)", [])?;
752 conn.execute("INSERT INTO test VALUES (42, 47)", [])?;
753 let val = conn.query_row("SELECT a, b FROM test", [], |row| <(u32, u32)>::try_from(row))?;
754 assert_eq!(val, (42, 47));
755 let fail = conn.query_row("SELECT a, b FROM test", [], |row| <(u32, u32, u32)>::try_from(row));
756 assert!(fail.is_err());
757 Ok(())
758 }
759
760 #[test]
761 fn test_try_from_row_for_tuple_3() -> Result<()> {
762 use std::convert::TryFrom;
763
764 let conn = Connection::open_in_memory()?;
765 let val = conn.query_row("SELECT 3, 5, 8", [], |row| <(u32, u32, u32)>::try_from(row))?;
766 assert_eq!(val, (3, 5, 8));
767 Ok(())
768 }
769
770 #[test]
771 fn test_try_from_row_for_tuple_16() -> Result<()> {
772 use std::convert::TryFrom;
773
774 let create_table = "CREATE TABLE test (
775 a INTEGER,
776 b INTEGER,
777 c INTEGER,
778 d INTEGER,
779 e INTEGER,
780 f INTEGER,
781 g INTEGER,
782 h INTEGER,
783 i INTEGER,
784 j INTEGER,
785 k INTEGER,
786 l INTEGER,
787 m INTEGER,
788 n INTEGER,
789 o INTEGER,
790 p INTEGER
791 )";
792
793 let insert_values = "INSERT INTO test VALUES (
794 0,
795 1,
796 2,
797 3,
798 4,
799 5,
800 6,
801 7,
802 8,
803 9,
804 10,
805 11,
806 12,
807 13,
808 14,
809 15
810 )";
811
812 type BigTuple = (
813 u32,
814 u32,
815 u32,
816 u32,
817 u32,
818 u32,
819 u32,
820 u32,
821 u32,
822 u32,
823 u32,
824 u32,
825 u32,
826 u32,
827 u32,
828 u32,
829 );
830
831 let conn = Connection::open_in_memory()?;
832 conn.execute(create_table, [])?;
833 conn.execute(insert_values, [])?;
834 let val = conn.query_row("SELECT * FROM test", [], |row| BigTuple::try_from(row))?;
835 assert_eq!(val.0, 0);
837 assert_eq!(val.1, 1);
838 assert_eq!(val.2, 2);
839 assert_eq!(val.3, 3);
840 assert_eq!(val.4, 4);
841 assert_eq!(val.5, 5);
842 assert_eq!(val.6, 6);
843 assert_eq!(val.7, 7);
844 assert_eq!(val.8, 8);
845 assert_eq!(val.9, 9);
846 assert_eq!(val.10, 10);
847 assert_eq!(val.11, 11);
848 assert_eq!(val.12, 12);
849 assert_eq!(val.13, 13);
850 assert_eq!(val.14, 14);
851 assert_eq!(val.15, 15);
852
853 Ok(())
855 }
856
857 #[test]
858 fn uhugeint_arrives_as_uhugeint() -> Result<()> {
859 let db = Connection::open_in_memory()?;
860
861 let mut stmt = db.prepare("SELECT (1)::UHUGEINT")?;
862 let mut rows = stmt.query([])?;
863 let row = rows.next()?.unwrap();
864 assert_eq!(row.get_ref(0)?, ValueRef::UHugeInt(1));
865 assert_eq!(row.get_ref(0)?.data_type(), Type::UHugeInt);
866 assert_eq!(row.get::<_, u128>(0)?, 1);
867
868 let mut stmt = db.prepare(&format!("SELECT ({U128_MAX_SQL})::UHUGEINT"))?;
869 let mut rows = stmt.query([])?;
870 let row = rows.next()?.unwrap();
871 assert_eq!(row.get_ref(0)?, ValueRef::UHugeInt(u128::MAX));
872 assert_eq!(row.get_ref(0)?.data_type(), Type::UHugeInt);
873 assert_eq!(row.get::<_, u128>(0)?, u128::MAX);
874
875 let i128_max_plus_one = (i128::MAX as u128) + 1;
876 let mut stmt = db.prepare(&format!("SELECT ({I128_MAX_PLUS_ONE_SQL})::UHUGEINT"))?;
877 let mut rows = stmt.query([])?;
878 let row = rows.next()?.unwrap();
879 assert_eq!(row.get_ref(0)?, ValueRef::UHugeInt(i128_max_plus_one));
880 assert_eq!(row.get::<_, u128>(0)?, i128_max_plus_one);
881
882 Ok(())
883 }
884
885 #[test]
886 fn uhugeint_promotion_uses_matching_result_column() -> Result<()> {
887 let db = Connection::open_in_memory()?;
888
889 let mut stmt = db.prepare(&format!(
890 "
891 SELECT
892 1::HUGEINT AS a,
893 2::UHUGEINT AS b,
894 3::DECIMAL(38,0) AS c,
895 ({U128_MAX_SQL})::UHUGEINT AS d
896 "
897 ))?;
898 let mut rows = stmt.query([])?;
899 let row = rows.next()?.unwrap();
900
901 assert_eq!(row.get_ref(0)?, ValueRef::HugeInt(1));
902 assert_eq!(row.get_ref(1)?, ValueRef::UHugeInt(2));
903 assert_eq!(row.get_ref(2)?, ValueRef::Decimal(Decimal::new(38, 0, 3)?));
904 assert_eq!(row.get_ref(3)?, ValueRef::UHugeInt(u128::MAX));
905
906 Ok(())
907 }
908
909 #[test]
910 fn bound_uhugeint_result_uses_logical_metadata_when_cast() -> Result<()> {
911 let db = Connection::open_in_memory()?;
912 let max = u128::MAX;
913
914 let value = db.query_row("SELECT ?::UHUGEINT", [&max], |row| {
915 assert_eq!(row.get_ref(0)?, ValueRef::UHugeInt(max));
916 row.get::<_, u128>(0)
917 })?;
918 assert_eq!(value, max);
919
920 Ok(())
921 }
922
923 #[test]
924 fn ambiguous_decimal_expression_uses_executed_metadata() -> Result<()> {
925 let db = Connection::open_in_memory()?;
926
927 let byte = 255_i128;
928 let byte_value = db.query_row("SELECT ?", [&byte], |row| {
929 assert_eq!(row.get_ref(0)?, ValueRef::HugeInt(byte));
930 row.get::<_, u8>(0)
931 })?;
932 assert_eq!(byte_value, 255);
933
934 let value = 5_u128;
935 let decimal = db.query_row("SELECT ? + 0::DECIMAL(38,0)", [&value], |row| {
936 row.get_ref(0).map(|value| value.to_owned())
937 })?;
938 assert_eq!(decimal, Value::Decimal(Decimal::new(38, 0, 5)?));
939
940 Ok(())
941 }
942
943 #[test]
944 fn decimal_columns_use_native_decimal_carrier() -> Result<()> {
945 let db = Connection::open_in_memory()?;
946
947 let value = db.query_row("SELECT 1.23::DECIMAL(38,2)", [], |row| {
948 row.get_ref(0).map(|value| value.to_owned())
949 })?;
950 assert_eq!(value, Value::Decimal(Decimal::new(38, 2, 123)?));
951
952 let value = db.query_row("SELECT 3::DECIMAL(38,0)", [], |row| {
953 row.get_ref(0).map(|value| value.to_owned())
954 })?;
955 match value {
956 Value::Decimal(decimal) => {
957 assert_eq!(decimal.width(), 38);
958 assert_eq!(decimal, Decimal::new(38, 0, 3)?);
959 }
960 other => panic!("expected decimal, got {other:?}"),
961 }
962
963 let decimal = db.query_row(&format!("SELECT {WIDE_DECIMAL_SQL}::DECIMAL(38,2)"), [], |row| {
964 assert_eq!(
965 row.get_ref(0)?,
966 ValueRef::Decimal(Decimal::new(38, 2, WIDE_DECIMAL_MANTISSA)?)
967 );
968 row.get::<_, Decimal>(0)
969 })?;
970 assert_eq!(decimal, Decimal::new(38, 2, WIDE_DECIMAL_MANTISSA)?);
971
972 Ok(())
973 }
974
975 #[test]
976 fn narrow_arrow_decimal_columns_use_native_decimal_carrier() -> Result<()> {
977 use arrow::datatypes::DataType;
978
979 let db = Connection::open_in_memory()?;
980 db.execute_batch("SET arrow_output_version = '1.5'")?;
981
982 {
983 let mut stmt = db.prepare("SELECT 1.23::DECIMAL(9,2) AS d32, 1.23::DECIMAL(18,2) AS d64")?;
984 let batch = stmt.query_arrow([])?.next().expect("no record batch");
985 assert_eq!(batch.column(0).data_type(), &DataType::Decimal32(9, 2));
986 assert_eq!(batch.column(1).data_type(), &DataType::Decimal64(18, 2));
987 }
988
989 let value = db.query_row("SELECT 1.23::DECIMAL(9,2)", [], |row| {
990 row.get_ref(0).map(|value| value.to_owned())
991 })?;
992 assert_eq!(value, Value::Decimal(Decimal::new(9, 2, 123)?));
993
994 let value = db.query_row("SELECT 1.23::DECIMAL(18,2)", [], |row| {
995 row.get_ref(0).map(|value| value.to_owned())
996 })?;
997 assert_eq!(value, Value::Decimal(Decimal::new(18, 2, 123)?));
998
999 Ok(())
1000 }
1001
1002 #[test]
1003 fn uhugeint_upper_half_is_out_of_range_for_i128() -> Result<()> {
1004 let db = Connection::open_in_memory()?;
1005
1006 let err = db
1007 .query_row(&format!("SELECT ({I128_MAX_PLUS_ONE_SQL})::UHUGEINT"), [], |row| {
1008 row.get::<_, i128>(0)
1009 })
1010 .unwrap_err();
1011
1012 match err {
1013 Error::UnsignedIntegralValueOutOfRange(0, value) => {
1014 assert_eq!(value, (i128::MAX as u128) + 1)
1015 }
1016 other => panic!("expected unsigned out-of-range error, got {other:?}"),
1017 }
1018
1019 let err = db
1020 .query_row(&format!("SELECT ({U128_MAX_SQL})::UHUGEINT"), [], |row| {
1021 row.get::<_, i128>(0)
1022 })
1023 .unwrap_err();
1024
1025 match err {
1026 Error::UnsignedIntegralValueOutOfRange(0, value) => assert_eq!(value, u128::MAX),
1027 other => panic!("expected unsigned out-of-range error, got {other:?}"),
1028 }
1029
1030 Ok(())
1031 }
1032
1033 #[test]
1034 fn nested_uhugeint_uses_metadata_less_hugeint_carrier() -> Result<()> {
1035 let db = Connection::open_in_memory()?;
1036
1037 let list = db.query_row(&format!("SELECT [({U128_MAX_SQL})::UHUGEINT]"), [], |row| {
1038 let value = row.get_ref(0)?;
1039 assert!(matches!(value.data_type(), Type::List(ref inner) if **inner == Type::Decimal));
1040 Ok(value.to_owned())
1041 })?;
1042
1043 assert_eq!(list, Value::List(vec![Value::HugeInt(-1)]));
1044
1045 let structure = db.query_row(
1046 &format!("SELECT struct_pack(v := ({U128_MAX_SQL})::UHUGEINT)"),
1047 [],
1048 |row| {
1049 let value = row.get_ref(0)?;
1050 assert!(matches!(value.data_type(), Type::Struct(_)));
1051 Ok(value.to_owned())
1052 },
1053 )?;
1054
1055 match structure {
1056 Value::Struct(fields) => {
1057 assert_eq!(fields.get(&"v".to_string()), Some(&Value::HugeInt(-1)));
1058 }
1059 other => panic!("expected struct, got {other:?}"),
1060 }
1061
1062 Ok(())
1063 }
1064
1065 #[test]
1066 fn nested_scale_zero_decimal_uses_decimal_when_width_is_unambiguous() -> Result<()> {
1067 let db = Connection::open_in_memory()?;
1068
1069 let list = db.query_row("SELECT [3::DECIMAL(5,0)]", [], |row| {
1070 let value = row.get_ref(0)?;
1071 assert!(matches!(value.data_type(), Type::List(ref inner) if **inner == Type::Decimal));
1072 Ok(value.to_owned())
1073 })?;
1074
1075 assert_eq!(list, Value::List(vec![Value::Decimal(Decimal::new(5, 0, 3)?)]));
1076
1077 let structure = db.query_row("SELECT struct_pack(a := 1.5::DECIMAL(5,1))", [], |row| {
1078 let value = row.get_ref(0)?;
1079 assert!(matches!(value.data_type(), Type::Struct(_)));
1080 Ok(value.to_owned())
1081 })?;
1082
1083 match structure {
1084 Value::Struct(fields) => {
1085 assert_eq!(
1086 fields.get(&"a".to_string()),
1087 Some(&Value::Decimal(Decimal::new(5, 1, 15)?))
1088 );
1089 }
1090 other => panic!("expected struct, got {other:?}"),
1091 }
1092
1093 Ok(())
1094 }
1095
1096 #[test]
1097 fn nested_decimal_38_0_keeps_metadata_less_hugeint_fallback() -> Result<()> {
1098 let db = Connection::open_in_memory()?;
1099
1100 let list = db.query_row("SELECT [3::DECIMAL(38,0)]", [], |row| {
1101 let value = row.get_ref(0)?;
1102 assert!(matches!(value.data_type(), Type::List(ref inner) if **inner == Type::Decimal));
1103 Ok(value.to_owned())
1104 })?;
1105
1106 assert_eq!(list, Value::List(vec![Value::HugeInt(3)]));
1107
1108 Ok(())
1109 }
1110
1111 #[test]
1112 fn nested_geometry_uses_metadata_less_blob_carrier() -> Result<()> {
1113 let db = Connection::open_in_memory()?;
1114
1115 let top_level = db.query_row("SELECT 'POINT EMPTY'::GEOMETRY", [], |row| {
1116 Ok(row.get_ref(0)?.to_owned())
1117 })?;
1118 assert!(matches!(top_level, Value::Geometry(_)));
1119
1120 let list = db.query_row("SELECT ['POINT EMPTY'::GEOMETRY]", [], |row| {
1121 let value = row.get_ref(0)?;
1122 assert!(matches!(value.data_type(), Type::List(ref inner) if **inner == Type::Blob));
1123 Ok(value.to_owned())
1124 })?;
1125
1126 assert!(matches!(list, Value::List(ref values) if matches!(values.as_slice(), [Value::Blob(_)])));
1127 Ok(())
1128 }
1129
1130 #[test]
1131 fn uhugeint_logical_type_cache_survives_later_batches() -> Result<()> {
1132 let db = Connection::open_in_memory()?;
1133
1134 let values = db
1135 .prepare(
1136 "
1137 SELECT
1138 CASE
1139 WHEN i = 2500 THEN NULL::UHUGEINT
1140 ELSE i::UHUGEINT
1141 END AS v
1142 FROM range(3000) AS t(i)
1143 ORDER BY i
1144 ",
1145 )?
1146 .query_map([], |row| row.get_ref(0).map(|value| value.to_owned()))?
1147 .collect::<Result<Vec<_>>>()?;
1148
1149 assert_eq!(values.len(), 3000);
1150 assert_eq!(values[0], Value::UHugeInt(0));
1151 assert_eq!(values[2048], Value::UHugeInt(2048));
1152 assert_eq!(values[2500], Value::Null);
1153 assert_eq!(values[2999], Value::UHugeInt(2999));
1154
1155 Ok(())
1156 }
1157
1158 #[test]
1159 fn zero_row_query_returns_none() -> Result<()> {
1160 let db = Connection::open_in_memory()?;
1161 let mut stmt = db.prepare("SELECT 1 AS x WHERE false")?;
1162 let mut rows = stmt.query([])?;
1163
1164 assert!(rows.next()?.is_none());
1165 assert!(rows.next()?.is_none());
1166
1167 Ok(())
1168 }
1169
1170 #[test]
1171 fn wide_multichunk_query_iterates_all_rows() -> Result<()> {
1172 let db = Connection::open_in_memory()?;
1173 let columns = (0..64)
1174 .map(|idx| format!("i + {idx} AS c{idx}"))
1175 .collect::<Vec<_>>()
1176 .join(", ");
1177 let sql = format!("SELECT {columns} FROM range(3000) AS t(i) ORDER BY i");
1178 let mut stmt = db.prepare(&sql)?;
1179 let mut rows = stmt.query([])?;
1180 let mut count = 0_i64;
1181
1182 while let Some(row) = rows.next()? {
1183 assert_eq!(row.get::<_, i64>(0)?, count);
1184 assert_eq!(row.get::<_, i64>(63)?, count + 63);
1185 count += 1;
1186 }
1187
1188 assert_eq!(count, 3000);
1189
1190 Ok(())
1191 }
1192
1193 #[test]
1194 fn uhugeint_nulls_use_cached_logical_type() -> Result<()> {
1195 let db = Connection::open_in_memory()?;
1196
1197 let values = db
1198 .prepare(&format!(
1199 "
1200 SELECT v FROM (
1201 VALUES
1202 (0, (0)::UHUGEINT),
1203 (1, NULL::UHUGEINT),
1204 (2, ({U128_MAX_SQL})::UHUGEINT)
1205 ) AS t(ord, v)
1206 ORDER BY ord
1207 "
1208 ))?
1209 .query_map([], |row| row.get_ref(0).map(|value| value.to_owned()))?
1210 .collect::<Result<Vec<_>>>()?;
1211
1212 assert_eq!(
1213 values,
1214 vec![Value::UHugeInt(0), Value::Null, Value::UHugeInt(u128::MAX)]
1215 );
1216
1217 Ok(())
1218 }
1219
1220 #[test]
1221 #[cfg(feature = "vtab-arrow")]
1222 fn test_fixed_size_binary_via_arrow() -> Result<()> {
1223 use crate::vtab::arrow::{ArrowVTab, arrow_recordbatch_to_query_params};
1224 use arrow::array::{Array, ArrayRef, BinaryArray, FixedSizeBinaryArray};
1225 use arrow::datatypes::{DataType, Field, Schema};
1226 use arrow::record_batch::RecordBatch;
1227 use std::sync::Arc;
1228
1229 let conn = Connection::open_in_memory()?;
1230 conn.register_table_function::<ArrowVTab>("arrow")?;
1231
1232 let values = vec![
1234 vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
1235 vec![16u8, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
1236 vec![0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255],
1237 ];
1238
1239 let byte_array = FixedSizeBinaryArray::try_from_iter(values.into_iter()).unwrap();
1240 let arc: ArrayRef = Arc::new(byte_array);
1241 let schema = Schema::new(vec![Field::new("data", DataType::FixedSizeBinary(16), false)]);
1242 let batch = RecordBatch::try_new(Arc::new(schema), vec![arc]).unwrap();
1243
1244 let mut stmt = conn.prepare("SELECT data FROM arrow(?, ?)")?;
1245 let mut arr = stmt.query_arrow(arrow_recordbatch_to_query_params(batch))?;
1246 let rb = arr.next().expect("no record batch");
1247
1248 let column = rb.column(0).as_any().downcast_ref::<BinaryArray>().unwrap();
1250 assert_eq!(column.len(), 3);
1251 assert_eq!(
1252 column.value(0),
1253 &[1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
1254 );
1255 assert_eq!(
1256 column.value(1),
1257 &[16u8, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
1258 );
1259 assert_eq!(column.value(2), &[0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255]);
1260
1261 Ok(())
1262 }
1263
1264 #[test]
1265 #[cfg(feature = "vtab-arrow")]
1266 fn test_fixed_size_binary_with_nulls_via_arrow() -> Result<()> {
1267 use crate::vtab::arrow::{ArrowVTab, arrow_recordbatch_to_query_params};
1268 use arrow::array::{Array, ArrayRef, BinaryArray, FixedSizeBinaryArray};
1269 use arrow::datatypes::{DataType, Field, Schema};
1270 use arrow::record_batch::RecordBatch;
1271 use std::sync::Arc;
1272
1273 let conn = Connection::open_in_memory()?;
1274 conn.register_table_function::<ArrowVTab>("arrow")?;
1275
1276 let values = vec![
1278 Some(vec![1u8, 2, 3, 4, 5, 6, 7, 8]),
1279 None,
1280 Some(vec![9u8, 10, 11, 12, 13, 14, 15, 16]),
1281 ];
1282
1283 let byte_array = FixedSizeBinaryArray::try_from_sparse_iter_with_size(values.into_iter(), 8).unwrap();
1284 let arc: ArrayRef = Arc::new(byte_array);
1285 let schema = Schema::new(vec![Field::new("data", DataType::FixedSizeBinary(8), true)]);
1286 let batch = RecordBatch::try_new(Arc::new(schema), vec![arc]).unwrap();
1287
1288 let mut stmt = conn.prepare("SELECT data FROM arrow(?, ?)")?;
1289 let mut arr = stmt.query_arrow(arrow_recordbatch_to_query_params(batch))?;
1290 let rb = arr.next().expect("no record batch");
1291
1292 let column = rb.column(0).as_any().downcast_ref::<BinaryArray>().unwrap();
1293 assert_eq!(column.len(), 3);
1294 assert!(column.is_valid(0));
1295 assert!(!column.is_valid(1));
1296 assert!(column.is_valid(2));
1297 assert_eq!(column.value(0), &[1u8, 2, 3, 4, 5, 6, 7, 8]);
1298 assert_eq!(column.value(2), &[9u8, 10, 11, 12, 13, 14, 15, 16]);
1299
1300 Ok(())
1301 }
1302
1303 #[test]
1304 #[cfg(feature = "vtab-arrow")]
1305 fn test_fixed_size_binary_different_sizes_via_arrow() -> Result<()> {
1306 use crate::vtab::arrow::{ArrowVTab, arrow_recordbatch_to_query_params};
1307 use arrow::array::{ArrayRef, FixedSizeBinaryArray};
1308 use arrow::datatypes::{DataType, Field, Schema};
1309 use arrow::record_batch::RecordBatch;
1310 use std::sync::Arc;
1311
1312 let conn = Connection::open_in_memory()?;
1313 conn.register_table_function::<ArrowVTab>("arrow")?;
1314
1315 let values = vec![vec![1u8, 2, 3, 4], vec![5u8, 6, 7, 8]];
1317
1318 let byte_array = FixedSizeBinaryArray::try_from_iter(values.into_iter()).unwrap();
1319 let arc: ArrayRef = Arc::new(byte_array);
1320 let schema = Schema::new(vec![Field::new("data", DataType::FixedSizeBinary(4), false)]);
1321 let batch = RecordBatch::try_new(Arc::new(schema), vec![arc]).unwrap();
1322
1323 let mut stmt = conn.prepare("SELECT data FROM arrow(?, ?)")?;
1324 let mut rows = stmt.query(arrow_recordbatch_to_query_params(batch))?;
1325
1326 let row = rows.next()?.unwrap();
1328 let bytes: Vec<u8> = row.get(0)?;
1329 assert_eq!(bytes, vec![1u8, 2, 3, 4]);
1330
1331 let row = rows.next()?.unwrap();
1332 let bytes: Vec<u8> = row.get(0)?;
1333 assert_eq!(bytes, vec![5u8, 6, 7, 8]);
1334
1335 Ok(())
1336 }
1337
1338 #[test]
1339 #[cfg(feature = "vtab-arrow")]
1340 fn test_fixed_size_binary_value_ref_via_arrow() -> Result<()> {
1341 use crate::types::ValueRef;
1342 use crate::vtab::arrow::{ArrowVTab, arrow_recordbatch_to_query_params};
1343 use arrow::array::{ArrayRef, FixedSizeBinaryArray};
1344 use arrow::datatypes::{DataType, Field, Schema};
1345 use arrow::record_batch::RecordBatch;
1346 use std::sync::Arc;
1347
1348 let conn = Connection::open_in_memory()?;
1349 conn.register_table_function::<ArrowVTab>("arrow")?;
1350
1351 let values = vec![Some(vec![1u8, 2, 3, 4]), None];
1352
1353 let byte_array = FixedSizeBinaryArray::try_from_sparse_iter_with_size(values.into_iter(), 4).unwrap();
1354 let arc: ArrayRef = Arc::new(byte_array);
1355 let schema = Schema::new(vec![Field::new("data", DataType::FixedSizeBinary(4), true)]);
1356 let batch = RecordBatch::try_new(Arc::new(schema), vec![arc]).unwrap();
1357
1358 let mut stmt = conn.prepare("SELECT data FROM arrow(?, ?)")?;
1359 let mut rows = stmt.query(arrow_recordbatch_to_query_params(batch))?;
1360
1361 let row = rows.next()?.unwrap();
1363 let value_ref = row.get_ref(0)?;
1364 match value_ref {
1365 ValueRef::Blob(bytes) => {
1366 assert_eq!(bytes, &[1u8, 2, 3, 4]);
1367 }
1368 _ => panic!("Expected Blob ValueRef, got {:?}", value_ref),
1369 }
1370
1371 let row = rows.next()?.unwrap();
1373 let value_ref = row.get_ref(0)?;
1374 match value_ref {
1375 ValueRef::Null => {}
1376 _ => panic!("Expected Null ValueRef, got {:?}", value_ref),
1377 }
1378
1379 Ok(())
1380 }
1381
1382 #[cfg(feature = "uuid")]
1383 #[test]
1384 fn test_fixed_size_binary_uuid() -> Result<()> {
1385 use uuid::Uuid;
1386
1387 let conn = Connection::open_in_memory()?;
1388 conn.execute_batch("CREATE TABLE test (id UUID)")?;
1389
1390 let uuid_str = "550e8400-e29b-41d4-a716-446655440000";
1391 conn.execute("INSERT INTO test VALUES (?)", [uuid_str])?;
1392
1393 let uuid: Uuid = conn.query_row("SELECT id FROM test", [], |r| r.get(0))?;
1395 assert_eq!(uuid.to_string(), uuid_str);
1396 Ok(())
1397 }
1398
1399 #[cfg(feature = "uuid")]
1400 #[test]
1401 fn test_fixed_size_binary_uuid_roundtrip() -> Result<()> {
1402 use uuid::Uuid;
1403
1404 let conn = Connection::open_in_memory()?;
1405 conn.execute_batch("CREATE TABLE test (id UUID)")?;
1406
1407 let original_uuid = Uuid::new_v4();
1408 conn.execute("INSERT INTO test VALUES (?)", [original_uuid])?;
1409
1410 let retrieved_uuid: Uuid = conn.query_row("SELECT id FROM test", [], |r| r.get(0))?;
1411 assert_eq!(original_uuid, retrieved_uuid);
1412 Ok(())
1413 }
1414}