sqlx_core/any/
row.rs

1use crate::any::error::mismatched_types;
2use crate::any::{Any, AnyColumn, AnyTypeInfo, AnyTypeInfoKind, AnyValue, AnyValueKind};
3use crate::column::{Column, ColumnIndex};
4use crate::database::Database;
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>(&self, index: I) -> Result<<Self::Database as Database>::ValueRef<'_>, Error>
32    where
33        I: ColumnIndex<Self>,
34    {
35        let index = index.index(self)?;
36        Ok(self
37            .values
38            .get(index)
39            .ok_or_else(|| Error::ColumnIndexOutOfBounds {
40                index,
41                len: self.columns.len(),
42            })?
43            .as_ref())
44    }
45
46    fn try_get<'r, T, I>(&'r self, index: I) -> Result<T, Error>
47    where
48        I: ColumnIndex<Self>,
49        T: Decode<'r, Self::Database> + Type<Self::Database>,
50    {
51        let value = self.try_get_raw(&index)?;
52        let ty = value.type_info();
53
54        if !value.is_null() && !ty.is_null() && !T::compatible(&ty) {
55            Err(mismatched_types::<T>(&ty))
56        } else {
57            T::decode(value)
58        }
59        .map_err(|source| Error::ColumnDecode {
60            index: format!("{index:?}"),
61            source,
62        })
63    }
64}
65
66impl<'i> ColumnIndex<AnyRow> for &'i str {
67    fn index(&self, row: &AnyRow) -> Result<usize, Error> {
68        row.column_names
69            .get(*self)
70            .copied()
71            .ok_or_else(|| Error::ColumnNotFound(self.to_string()))
72    }
73}
74
75impl AnyRow {
76    // This is not a `TryFrom` impl because trait impls are easy for users to accidentally
77    // become reliant upon, even if hidden, but we want to be able to change the bounds
78    // on this function as the `Any` driver gains support for more types.
79    //
80    // Also `column_names` needs to be passed by the driver to avoid making deep copies.
81    #[doc(hidden)]
82    pub fn map_from<'a, R: Row>(
83        row: &'a R,
84        column_names: Arc<crate::HashMap<UStr, usize>>,
85    ) -> Result<Self, Error>
86    where
87        usize: ColumnIndex<R>,
88        AnyTypeInfo: for<'b> TryFrom<&'b <R::Database as Database>::TypeInfo, Error = Error>,
89        AnyColumn: for<'b> TryFrom<&'b <R::Database as Database>::Column, Error = Error>,
90        bool: Type<R::Database> + Decode<'a, R::Database>,
91        i16: Type<R::Database> + Decode<'a, R::Database>,
92        i32: Type<R::Database> + Decode<'a, R::Database>,
93        i64: Type<R::Database> + Decode<'a, R::Database>,
94        f32: Type<R::Database> + Decode<'a, R::Database>,
95        f64: Type<R::Database> + Decode<'a, R::Database>,
96        String: Type<R::Database> + Decode<'a, R::Database>,
97        Vec<u8>: Type<R::Database> + Decode<'a, R::Database>,
98    {
99        let mut row_out = AnyRow {
100            column_names,
101            columns: Vec::with_capacity(row.columns().len()),
102            values: Vec::with_capacity(row.columns().len()),
103        };
104
105        for col in row.columns() {
106            let i = col.ordinal();
107
108            let any_col = AnyColumn::try_from(col)?;
109
110            let value = row.try_get_raw(i)?;
111
112            // Map based on the _value_ type info, not the column type info.
113            let type_info =
114                AnyTypeInfo::try_from(&value.type_info()).map_err(|e| Error::ColumnDecode {
115                    index: col.ordinal().to_string(),
116                    source: e.into(),
117                })?;
118
119            let value_kind = match type_info.kind {
120                k if value.is_null() => AnyValueKind::Null(k),
121                AnyTypeInfoKind::Null => AnyValueKind::Null(AnyTypeInfoKind::Null),
122                AnyTypeInfoKind::Bool => AnyValueKind::Bool(decode(value)?),
123                AnyTypeInfoKind::SmallInt => AnyValueKind::SmallInt(decode(value)?),
124                AnyTypeInfoKind::Integer => AnyValueKind::Integer(decode(value)?),
125                AnyTypeInfoKind::BigInt => AnyValueKind::BigInt(decode(value)?),
126                AnyTypeInfoKind::Real => AnyValueKind::Real(decode(value)?),
127                AnyTypeInfoKind::Double => AnyValueKind::Double(decode(value)?),
128                AnyTypeInfoKind::Blob => AnyValueKind::Blob(decode::<_, Vec<u8>>(value)?.into()),
129                AnyTypeInfoKind::Text => AnyValueKind::Text(decode::<_, String>(value)?.into()),
130            };
131
132            row_out.columns.push(any_col);
133            row_out.values.push(AnyValue { kind: value_kind });
134        }
135
136        Ok(row_out)
137    }
138}
139
140fn decode<'r, DB: Database, T: Decode<'r, DB>>(
141    valueref: <DB as Database>::ValueRef<'r>,
142) -> crate::Result<T> {
143    Decode::decode(valueref).map_err(Error::decode)
144}