1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
pub use crate::tds::stream::{QueryItem, ResultMetadata};
use crate::{
client::Connection,
tds::stream::{ReceivedToken, TokenStream},
};
use futures::{AsyncRead, AsyncWrite, TryStreamExt};
use std::fmt::Debug;
/// A result from a query execution, listing the number of affected rows.
///
/// If executing multiple queries, the resulting counts will be come separately,
/// marking the rows affected for each query.
///
/// # Example
///
/// ```no_run
/// # use tiberius::Config;
/// # use tokio_util::compat::TokioAsyncWriteCompatExt;
/// # use std::env;
/// # #[tokio::main]
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # let c_str = env::var("TIBERIUS_TEST_CONNECTION_STRING").unwrap_or(
/// # "server=tcp:localhost,1433;integratedSecurity=true;TrustServerCertificate=true".to_owned(),
/// # );
/// # let config = Config::from_ado_string(&c_str)?;
/// # let tcp = tokio::net::TcpStream::connect(config.get_addr()).await?;
/// # tcp.set_nodelay(true)?;
/// # let mut client = tiberius::Client::connect(config, tcp.compat_write()).await?;
/// let result = client
/// .execute(
/// "INSERT INTO #Test (id) VALUES (@P1); INSERT INTO #Test (id) VALUES (@P2, @P3)",
/// &[&1i32, &2i32, &3i32],
/// )
/// .await?;
///
/// assert_eq!(&[1, 2], result.rows_affected());
/// # Ok(())
/// # }
/// ```
///
/// [`Client`]: struct.Client.html
/// [`Rows`]: struct.Row.html
/// [`next_resultset`]: #method.next_resultset
#[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 })
}
/// A slice of numbers of rows affected in the same order as the given
/// queries.
pub fn rows_affected(&self) -> &[u64] {
self.rows_affected.as_slice()
}
/// Aggregates all resulting row counts into a sum.
///
/// # Example
///
/// ```no_run
/// # use tiberius::Config;
/// # use tokio_util::compat::TokioAsyncWriteCompatExt;
/// # use std::env;
/// # #[tokio::main]
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # let c_str = env::var("TIBERIUS_TEST_CONNECTION_STRING").unwrap_or(
/// # "server=tcp:localhost,1433;integratedSecurity=true;TrustServerCertificate=true".to_owned(),
/// # );
/// # let config = Config::from_ado_string(&c_str)?;
/// # let tcp = tokio::net::TcpStream::connect(config.get_addr()).await?;
/// # tcp.set_nodelay(true)?;
/// # let mut client = tiberius::Client::connect(config, tcp.compat_write()).await?;
/// let rows_affected = client
/// .execute(
/// "INSERT INTO #Test (id) VALUES (@P1); INSERT INTO #Test (id) VALUES (@P2, @P3)",
/// &[&1i32, &2i32, &3i32],
/// )
/// .await?;
///
/// assert_eq!(3, rows_affected.total());
/// # Ok(())
/// # }
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()
}
}