1use crate::any::error::mismatched_types;
2use crate::any::{Any, AnyColumn, AnyTypeInfo, AnyTypeInfoKind, AnyValue, AnyValueKind};
3use crate::column::{Column, ColumnIndex};
4use crate::database::{Database, HasValueRef};
5use crate::decode::Decode;
6use crate::error::Error;
7use crate::ext::ustr::UStr;
8use crate::row::Row;
9use crate::type_info::TypeInfo;
10use crate::types::Type;
11use crate::value::{Value, ValueRef};
12use std::sync::Arc;
13
14#[derive(Clone)]
15pub struct AnyRow {
16 #[doc(hidden)]
17 pub column_names: Arc<crate::HashMap<UStr, usize>>,
18 #[doc(hidden)]
19 pub columns: Vec<AnyColumn>,
20 #[doc(hidden)]
21 pub values: Vec<AnyValue>,
22}
23
24impl Row for AnyRow {
25 type Database = Any;
26
27 fn columns(&self) -> &[AnyColumn] {
28 &self.columns
29 }
30
31 fn try_get_raw<I>(
32 &self,
33 index: I,
34 ) -> Result<<Self::Database as HasValueRef<'_>>::ValueRef, Error>
35 where
36 I: ColumnIndex<Self>,
37 {
38 let index = index.index(self)?;
39 Ok(self
40 .values
41 .get(index)
42 .ok_or_else(|| Error::ColumnIndexOutOfBounds {
43 index,
44 len: self.columns.len(),
45 })?
46 .as_ref())
47 }
48
49 fn try_get<'r, T, I>(&'r self, index: I) -> Result<T, Error>
50 where
51 I: ColumnIndex<Self>,
52 T: Decode<'r, Self::Database> + Type<Self::Database>,
53 {
54 let value = self.try_get_raw(&index)?;
55 let ty = value.type_info();
56
57 if !value.is_null() && !ty.is_null() && !T::compatible(&ty) {
58 Err(mismatched_types::<T>(&ty))
59 } else {
60 T::decode(value)
61 }
62 .map_err(|source| Error::ColumnDecode {
63 index: format!("{index:?}"),
64 source,
65 })
66 }
67}
68
69impl<'i> ColumnIndex<AnyRow> for &'i str {
70 fn index(&self, row: &AnyRow) -> Result<usize, Error> {
71 row.column_names
72 .get(*self)
73 .copied()
74 .ok_or_else(|| Error::ColumnNotFound(self.to_string()))
75 }
76}
77
78impl AnyRow {
79 #[doc(hidden)]
85 pub fn map_from<'a, R: Row>(
86 row: &'a R,
87 column_names: Arc<crate::HashMap<UStr, usize>>,
88 ) -> Result<Self, Error>
89 where
90 usize: ColumnIndex<R>,
91 AnyTypeInfo: for<'b> TryFrom<&'b <R::Database as Database>::TypeInfo, Error = Error>,
92 AnyColumn: for<'b> TryFrom<&'b <R::Database as Database>::Column, Error = Error>,
93 bool: Type<R::Database> + Decode<'a, R::Database>,
94 i16: Type<R::Database> + Decode<'a, R::Database>,
95 i32: Type<R::Database> + Decode<'a, R::Database>,
96 i64: Type<R::Database> + Decode<'a, R::Database>,
97 f32: Type<R::Database> + Decode<'a, R::Database>,
98 f64: Type<R::Database> + Decode<'a, R::Database>,
99 String: Type<R::Database> + Decode<'a, R::Database>,
100 Vec<u8>: Type<R::Database> + Decode<'a, R::Database>,
101 {
102 let mut row_out = AnyRow {
103 column_names,
104 columns: Vec::with_capacity(row.columns().len()),
105 values: Vec::with_capacity(row.columns().len()),
106 };
107
108 for col in row.columns() {
109 let i = col.ordinal();
110
111 let any_col = AnyColumn::try_from(col)?;
112
113 let value = row.try_get_raw(i)?;
114
115 let type_info =
117 AnyTypeInfo::try_from(&value.type_info()).map_err(|e| Error::ColumnDecode {
118 index: col.ordinal().to_string(),
119 source: e.into(),
120 })?;
121
122 let value_kind = match type_info.kind {
123 _ if value.is_null() => AnyValueKind::Null,
124 AnyTypeInfoKind::Null => AnyValueKind::Null,
125 AnyTypeInfoKind::Bool => AnyValueKind::Bool(decode(value)?),
126 AnyTypeInfoKind::SmallInt => AnyValueKind::SmallInt(decode(value)?),
127 AnyTypeInfoKind::Integer => AnyValueKind::Integer(decode(value)?),
128 AnyTypeInfoKind::BigInt => AnyValueKind::BigInt(decode(value)?),
129 AnyTypeInfoKind::Real => AnyValueKind::Real(decode(value)?),
130 AnyTypeInfoKind::Double => AnyValueKind::Double(decode(value)?),
131 AnyTypeInfoKind::Blob => AnyValueKind::Blob(decode::<_, Vec<u8>>(value)?.into()),
132 AnyTypeInfoKind::Text => AnyValueKind::Text(decode::<_, String>(value)?.into()),
133 };
134
135 row_out.columns.push(any_col);
136 row_out.values.push(AnyValue { kind: value_kind });
137 }
138
139 Ok(row_out)
140 }
141}
142
143fn decode<'r, DB: Database, T: Decode<'r, DB>>(
144 valueref: <DB as HasValueRef<'r>>::ValueRef,
145) -> crate::Result<T> {
146 Decode::decode(valueref).map_err(Error::decode)
147}