wick-sql 0.3.0

SQL Database component for the wick project.
Documentation
use chrono::{DateTime, NaiveDate, NaiveTime, TimeZone, Utc};
use serde_json::{Number, Value};
use tiberius::{ColumnData, FromSql, IntoSql};

use crate::common::sql_wrapper::ConvertedType;

impl<'a> IntoSql<'a> for ConvertedType {
  fn into_sql(self) -> ColumnData<'a> {
    match self {
      ConvertedType::I8(v) => v.into_sql(),
      ConvertedType::I16(v) => v.into_sql(),
      ConvertedType::I32(v) => v.into_sql(),
      ConvertedType::I64(v) => v.into_sql(),
      ConvertedType::U8(v) => v.into_sql(),
      ConvertedType::U16(v) => v.into_sql(),
      ConvertedType::U32(v) => v.into_sql(),
      ConvertedType::U64(v) => v.into_sql(),
      ConvertedType::F32(v) => v.into_sql(),
      ConvertedType::F64(v) => v.into_sql(),
      ConvertedType::Bool(v) => v.into_sql(),
      ConvertedType::String(v) => v.into_sql(),
      ConvertedType::Datetime(v) => v.into_sql(),
    }
  }
}

pub(crate) struct FromSqlWrapper(pub(crate) Value);

impl<'a> FromSql<'a> for FromSqlWrapper {
  fn from_sql(col: &'a ColumnData<'static>) -> tiberius::Result<Option<Self>> {
    let value: Option<Value> = match col {
      ColumnData::U8(v) => v.map(Into::into),
      ColumnData::I16(v) => v.map(Into::into),
      ColumnData::I32(v) => v.map(Into::into),
      ColumnData::I64(v) => v.map(Into::into),
      ColumnData::F32(v) => v.map(Into::into),
      ColumnData::F64(v) => v.map(Into::into),
      ColumnData::Bit(v) => v.map(Into::into),
      ColumnData::String(v) => v.clone().map(|v| v.into()),
      ColumnData::Guid(v) => v.map(|v| Value::from(v.to_string())),
      ColumnData::Binary(v) => v
        .clone()
        .map(|v| Value::Array(v.iter().copied().map(|v| Value::Number(Number::from(v))).collect())),
      ColumnData::Numeric(v) => v.map(|v| {
        let v: i64 = v.value().try_into().unwrap();
        Value::Number(Number::from(v))
      }),
      ColumnData::Xml(_) => unimplemented!(),
      ColumnData::DateTime(_) | ColumnData::SmallDateTime(_) | ColumnData::DateTime2(_) => {
        tiberius::time::chrono::NaiveDateTime::from_sql(col)?
          .map(|d| Value::String(Utc.from_utc_datetime(&d).to_rfc3339()))
      }
      ColumnData::DateTimeOffset(_) => DateTime::<Utc>::from_sql(col)?.map(|d| Value::String(d.to_rfc3339())),
      ColumnData::Time(_) => NaiveTime::from_sql(col)?.map(|d| Value::String(d.to_string())),
      ColumnData::Date(_) => NaiveDate::from_sql(col)?.map(|d| Value::String(d.to_string())),
    };
    Ok(value.map(FromSqlWrapper))
  }
}