pub use crate::tds::stream::{CommandItem, QueryItem, ResultMetadata};
use crate::{
client::Connection,
error::Error,
tds::stream::{CommandReturnValue, ReceivedToken, TokenStream},
FromSql, Row,
};
use futures_util::io::{AsyncRead, AsyncWrite};
use futures_util::stream::TryStreamExt;
use std::fmt::Debug;
#[derive(Debug)]
pub struct ExecuteResult {
rows_affected: Vec<u64>,
}
impl<'a> ExecuteResult {
pub(crate) async fn new<S: AsyncRead + AsyncWrite + Unpin + Send>(
connection: &'a mut Connection<S>,
) -> crate::Result<Self> {
let mut token_stream = TokenStream::new(connection).try_unfold();
let mut rows_affected = Vec::new();
while let Some(token) = token_stream.try_next().await? {
match token {
ReceivedToken::DoneProc(done) if done.is_final() => (),
ReceivedToken::DoneProc(done) => rows_affected.push(done.rows()),
ReceivedToken::DoneInProc(done) => rows_affected.push(done.rows()),
ReceivedToken::Done(done) => rows_affected.push(done.rows()),
_ => (),
}
}
Ok(Self { rows_affected })
}
pub fn rows_affected(&self) -> &[u64] {
self.rows_affected.as_slice()
}
pub fn total(self) -> u64 {
self.rows_affected.into_iter().sum()
}
}
impl IntoIterator for ExecuteResult {
type Item = u64;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.rows_affected.into_iter()
}
}
#[derive(Debug)]
pub struct CommandResult {
pub(crate) rows_affected: Vec<u64>,
pub(crate) return_code: u32,
pub(crate) return_values: Vec<CommandReturnValue>,
pub(crate) query_results: Vec<Vec<Row>>,
}
impl<'a> CommandResult {
pub fn rows_affected(&self) -> &[u64] {
self.rows_affected.as_slice()
}
pub fn return_code(&self) -> u32 {
self.return_code
}
pub fn return_values_len(&self) -> usize {
self.return_values.len()
}
pub fn try_return_value<T>(&'a self, name: &str) -> crate::Result<Option<T>>
where
T: FromSql<'a>,
{
let col_data = self
.return_values
.iter()
.find(|p| p.name.eq(name))
.ok_or_else(|| {
Error::Conversion(format!("Could not find return value {}", name).into())
})?;
T::from_sql(&col_data.data)
}
pub fn to_query_result(&self, idx: usize) -> Option<&Vec<Row>> {
self.query_results.get(idx)
}
}
impl IntoIterator for CommandResult {
type Item = Vec<Row>;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.query_results.into_iter()
}
}