use super::super::MssqlParam;
use super::Param;
use super::TiberiusConn;
use crate::errors::Result;
use crate::row::Row;
use async_mutex::MutexGuard;
use futures::Stream;
use futures::StreamExt;
use futures_core::stream::BoxStream;
use std::pin::Pin;
use tiberius::ToSql;
pub(crate) struct PooledConnectionStream<'e> {
guard: MutexGuard<'e, Option<TiberiusConn>>,
stream: Option<BoxStream<'e, Result<Row>>>,
}
impl<'e> PooledConnectionStream<'e> {
pub async fn new<'params>(
guard: MutexGuard<'e, Option<TiberiusConn>>,
sql: &str,
params: &[&'params (dyn Param + Sync)],
) -> Pin<Box<Self>>
where
'params: 'e,
{
let mut gs = Box::new(PooledConnectionStream {
stream: None,
guard,
});
let mut args: Vec<&dyn ToSql> = Vec::new();
for &p in params {
args = MssqlParam::add_param(p, args);
}
let stream_result = unsafe {
let conn: *mut TiberiusConn = gs.guard.as_mut().unwrap();
(&mut *conn).query(sql, &args).await
};
let stream: BoxStream<'e, Result<Row>> = match stream_result {
Err(err) => futures::stream::iter([Err(crate::errors::Error::Tiberius(err))]).boxed(),
Ok(s) => s
.into_row_stream()
.map(|x| x.map_err(crate::Error::Tiberius).map(Row::from))
.boxed(),
};
gs.stream = Some(stream);
Box::into_pin(gs)
}
}
impl<'e> Stream for PooledConnectionStream<'e> {
type Item = Result<Row>;
fn poll_next(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> {
let stream = &mut self.get_mut().stream.as_mut().unwrap();
stream.poll_next_unpin(cx)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let stream = self.stream.as_ref().unwrap();
Stream::size_hint(stream)
}
}