use crate::any::error::mismatched_types; use crate::any::{Any, AnyColumn, AnyTypeInfo, AnyTypeInfoKind, AnyValue, AnyValueKind}; use crate::column::{Column, ColumnIndex}; use crate::database::Database; use crate::decode::Decode; use crate::error::Error; use crate::ext::ustr::UStr; use crate::row::Row; use crate::type_info::TypeInfo; use crate::types::Type; use crate::value::{Value, ValueRef}; use std::sync::Arc; #[derive(Clone)] pub struct AnyRow { #[doc(hidden)] pub column_names: Arc>, #[doc(hidden)] pub columns: Vec, #[doc(hidden)] pub values: Vec, } impl Row for AnyRow { type Database = Any; fn columns(&self) -> &[AnyColumn] { &self.columns } fn try_get_raw(&self, index: I) -> Result<::ValueRef<'_>, Error> where I: ColumnIndex, { let index = index.index(self)?; Ok(self .values .get(index) .ok_or_else(|| Error::ColumnIndexOutOfBounds { index, len: self.columns.len(), })? .as_ref()) } fn try_get<'r, T, I>(&'r self, index: I) -> Result where I: ColumnIndex, T: Decode<'r, Self::Database> + Type, { let value = self.try_get_raw(&index)?; let ty = value.type_info(); if !value.is_null() && !ty.is_null() && !T::compatible(&ty) { Err(mismatched_types::(&ty)) } else { T::decode(value) } .map_err(|source| Error::ColumnDecode { index: format!("{index:?}"), source, }) } } impl ColumnIndex for &'_ str { fn index(&self, row: &AnyRow) -> Result { row.column_names .get(*self) .copied() .ok_or_else(|| Error::ColumnNotFound(self.to_string())) } } impl AnyRow { // This is not a `TryFrom` impl because trait impls are easy for users to accidentally // become reliant upon, even if hidden, but we want to be able to change the bounds // on this function as the `Any` driver gains support for more types. // // Also `column_names` needs to be passed by the driver to avoid making deep copies. #[doc(hidden)] pub fn map_from<'a, R: Row>( row: &'a R, column_names: Arc>, ) -> Result where usize: ColumnIndex, AnyTypeInfo: for<'b> TryFrom<&'b ::TypeInfo, Error = Error>, AnyColumn: for<'b> TryFrom<&'b ::Column, Error = Error>, bool: Type + Decode<'a, R::Database>, i16: Type + Decode<'a, R::Database>, i32: Type + Decode<'a, R::Database>, i64: Type + Decode<'a, R::Database>, f32: Type + Decode<'a, R::Database>, f64: Type + Decode<'a, R::Database>, String: Type + Decode<'a, R::Database>, Vec: Type + Decode<'a, R::Database>, { let mut row_out = AnyRow { column_names, columns: Vec::with_capacity(row.columns().len()), values: Vec::with_capacity(row.columns().len()), }; for col in row.columns() { let i = col.ordinal(); let any_col = AnyColumn::try_from(col)?; let value = row.try_get_raw(i)?; // Map based on the _value_ type info, not the column type info. let type_info = AnyTypeInfo::try_from(&value.type_info()).map_err(|e| Error::ColumnDecode { index: col.ordinal().to_string(), source: e.into(), })?; let value_kind = match type_info.kind { k if value.is_null() => AnyValueKind::Null(k), AnyTypeInfoKind::Null => AnyValueKind::Null(AnyTypeInfoKind::Null), AnyTypeInfoKind::Bool => AnyValueKind::Bool(decode(value)?), AnyTypeInfoKind::SmallInt => AnyValueKind::SmallInt(decode(value)?), AnyTypeInfoKind::Integer => AnyValueKind::Integer(decode(value)?), AnyTypeInfoKind::BigInt => AnyValueKind::BigInt(decode(value)?), AnyTypeInfoKind::Real => AnyValueKind::Real(decode(value)?), AnyTypeInfoKind::Double => AnyValueKind::Double(decode(value)?), AnyTypeInfoKind::Blob => AnyValueKind::Blob(decode::<_, Vec>(value)?.into()), AnyTypeInfoKind::Text => AnyValueKind::Text(decode::<_, String>(value)?.into()), }; row_out.columns.push(any_col); row_out.values.push(AnyValue { kind: value_kind }); } Ok(row_out) } } fn decode<'r, DB: Database, T: Decode<'r, DB>>( valueref: ::ValueRef<'r>, ) -> crate::Result { Decode::decode(valueref).map_err(Error::decode) }