use std::borrow::Cow;
use crate::{DynamicValue, NativeclickError, Result, Value, types::Type};
mod raw_row;
mod std_deserialize;
mod std_serialize;
pub use raw_row::*;
mod unit_value;
pub use unit_value::*;
mod vec_tuple;
pub use vec_tuple::*;
#[cfg(feature = "serde")]
mod json;
#[cfg(feature = "serde")]
pub use json::*;
pub trait ToSql {
fn to_sql(self, type_hint: Option<&Type>) -> Result<Value>;
}
impl ToSql for Value {
fn to_sql(self, _type_hint_: Option<&Type>) -> Result<Value> {
Ok(self)
}
}
pub fn unexpected_type(type_: &Type) -> NativeclickError {
NativeclickError::DeserializeError(format!("unexpected type: {type_}"))
}
pub trait FromSql: Sized {
fn from_sql(type_: &Type, value: Value) -> Result<Self>;
fn from_sql_column(type_: &Type, value: Value) -> Result<Self> {
let (type_, value) = resolve(type_, value);
Self::from_sql(&type_, value)
}
}
impl FromSql for Value {
fn from_sql(_type_: &Type, value: Value) -> Result<Self> {
Ok(value)
}
fn from_sql_column(_type_: &Type, value: Value) -> Result<Self> {
Ok(value)
}
}
pub fn from_sql_resolved<T: FromSql>(type_: &Type, value: Value) -> Result<T> {
T::from_sql_column(type_, value)
}
pub(crate) fn resolve(type_: &Type, value: Value) -> (Cow<'_, Type>, Value) {
match (type_, value) {
(_, Value::Dynamic(dynamic)) => {
let DynamicValue { type_, value } = *dynamic;
let (resolved, value) = resolve(&type_, value);
(Cow::Owned(resolved.into_owned()), value)
}
(Type::LowCardinality(inner) | Type::SimpleAggregateFunction(_, inner), value) => {
resolve(inner, value)
}
(Type::Variant(_) | Type::Dynamic(_) | Type::Geometry, Value::Null) => (
Cow::Owned(Type::Nullable(Box::new(Type::Nothing))),
Value::Null,
),
(Type::Interval(_), value) => (Cow::Owned(Type::Int64), value),
(Type::Json(_), value) => (Cow::Owned(Type::String), value),
(Type::LineString | Type::MultiPoint, value) => (Cow::Owned(Type::Ring), value),
(Type::MultiLineString, value) => (Cow::Owned(Type::Polygon), value),
(Type::NamedTuple(items), value) => (
Cow::Owned(Type::Tuple(items.iter().map(|x| x.1.clone()).collect())),
value,
),
(type_, value) => (Cow::Borrowed(type_), value),
}
}
pub trait Row: Sized {
const COLUMN_COUNT: Option<usize>;
fn column_names() -> Option<Vec<Cow<'static, str>>>;
fn deserialize_row(map: Vec<(&str, &Type, Value)>) -> Result<Self>;
fn serialize_row(
self,
type_hints: &indexmap::IndexMap<String, Type>,
) -> Result<Vec<(Cow<'static, str>, Value)>>;
}