(
client: &'c mut tiberius::Client<Compat<TcpStream>>,
kind: RequestKind,
)
| 634 | } |
| 635 | |
| 636 | async fn handle_request<'c>( |
| 637 | client: &'c mut tiberius::Client<Compat<TcpStream>>, |
| 638 | kind: RequestKind, |
| 639 | ) -> Result<(Response, Option<BoxFuture<'c, ()>>), SqlServerError> { |
| 640 | match kind { |
| 641 | RequestKind::Execute { query, params } => { |
| 642 | #[allow(clippy::as_conversions)] |
| 643 | let params: SmallVec<[&dyn ToSql; 4]> = |
| 644 | params.iter().map(|x| x as &dyn ToSql).collect(); |
| 645 | let result = client.execute(query, ¶ms[..]).await?; |
| 646 | |
| 647 | match result.rows_affected() { |
| 648 | rows_affected => { |
| 649 | let response = Response::Execute { |
| 650 | rows_affected: rows_affected.into(), |
| 651 | }; |
| 652 | Ok((response, None)) |
| 653 | } |
| 654 | } |
| 655 | } |
| 656 | RequestKind::Query { query, params } => { |
| 657 | #[allow(clippy::as_conversions)] |
| 658 | let params: SmallVec<[&dyn ToSql; 4]> = |
| 659 | params.iter().map(|x| x as &dyn ToSql).collect(); |
| 660 | let result = client.query(query, params.as_slice()).await?; |
| 661 | |
| 662 | let mut results = result.into_results().await.context("into results")?; |
| 663 | if results.is_empty() { |
| 664 | Ok((Response::Rows(smallvec![]), None)) |
| 665 | } else if results.len() == 1 { |
| 666 | // TODO(sql_server3): Don't use `into_results()` above, instead directly |
| 667 | // push onto a SmallVec to avoid the heap allocations. |
| 668 | let rows = results.pop().expect("checked len").into(); |
| 669 | Ok((Response::Rows(rows), None)) |
| 670 | } else { |
| 671 | Err(SqlServerError::ProgrammingError(format!( |
| 672 | "Query only supports 1 statement, got {}", |
| 673 | results.len() |
| 674 | ))) |
| 675 | } |
| 676 | } |
| 677 | RequestKind::QueryStreamed { query, params } => { |
| 678 | #[allow(clippy::as_conversions)] |
| 679 | let params: SmallVec<[&dyn ToSql; 4]> = |
| 680 | params.iter().map(|x| x as &dyn ToSql).collect(); |
| 681 | let result = client.query(query, params.as_slice()).await?; |
| 682 | |
| 683 | // ~~ Rust Lifetimes ~~ |
| 684 | // |
| 685 | // What's going on here, why do we have some extra channel and |
| 686 | // this 'work' future? |
| 687 | // |
| 688 | // Remember, we run the actual `tiberius::Client` in a separate |
| 689 | // `tokio::task` and the `mz::Client` sends query requests via |
| 690 | // a channel, this allows us to "automatically" manage |
| 691 | // transactions. |
| 692 | // |
| 693 | // But the returned `QueryStream` from a `tiberius::Client` has |
no test coverage detected