use std::borrow::Cow;
use std::fmt::Write;
use tiberius::{ColumnData, ToSql};
use crate::middleware::{ConversionMode, ParamConverter, RowValues, SqlMiddlewareDbError};
#[allow(dead_code)]
pub struct Params<'a> {
pub(crate) references: Vec<&'a (dyn ToSql + Sync)>,
}
impl<'a> Params<'a> {
#[allow(dead_code)]
pub fn convert(params: &'a [RowValues]) -> Result<Params<'a>, SqlMiddlewareDbError> {
let mut references = Vec::with_capacity(params.len());
for p in params {
references.push(p as &(dyn ToSql + Sync));
}
Ok(Params { references })
}
#[must_use]
#[allow(dead_code)]
pub fn as_refs(&self) -> &[&(dyn ToSql + Sync)] {
&self.references
}
}
impl<'a> ParamConverter<'a> for Params<'a> {
type Converted = Params<'a>;
fn convert_sql_params(
params: &'a [RowValues],
_mode: ConversionMode,
) -> Result<Self::Converted, SqlMiddlewareDbError> {
Self::convert(params)
}
fn supports_mode(_mode: ConversionMode) -> bool {
true
}
}
impl ToSql for RowValues {
fn to_sql(&self) -> tiberius::ColumnData<'_> {
match self {
RowValues::Int(i) => ColumnData::I64(Some(*i)),
RowValues::Float(f) => ColumnData::F64(Some(*f)),
RowValues::Text(s) => ColumnData::String(Some(Cow::from(s.as_str()))),
RowValues::Bool(b) => ColumnData::Bit(Some(*b)),
RowValues::Timestamp(dt) => {
thread_local! {
static BUF: std::cell::RefCell<String> = std::cell::RefCell::new(String::with_capacity(32));
}
BUF.with(|buf| {
let mut s = buf.borrow_mut();
s.clear();
write!(s, "{}", dt.format("%Y-%m-%dT%H:%M:%S%.f")).unwrap();
ColumnData::String(Some(Cow::from(s.clone())))
})
}
RowValues::Null => ColumnData::String(None),
RowValues::JSON(jsval) => ColumnData::String(Some(Cow::from(jsval.to_string()))),
RowValues::Blob(bytes) => ColumnData::Binary(Some(Cow::from(bytes.as_slice()))),
}
}
}