tarantool_rs/client/sql/
prepared_statement.rs1use std::result::Result as StdResult;
2
3use rmpv::Value;
4
5use crate::{
6 codec::{consts::keys, request::Execute},
7 errors::DecodingError,
8 utils::{find_and_take_single_key_in_map, value_to_map},
9 Executor, ExecutorExt, Result, SqlResponse, Tuple,
10};
11
12#[derive(Debug)]
13pub struct PreparedSqlStatement<E> {
14 stmt_id: u64,
15 executor: E,
16}
17
18impl<E> PreparedSqlStatement<E> {
19 fn new(stmt_id: u64, executor: E) -> Self {
20 Self { stmt_id, executor }
21 }
22
23 pub fn from_prepare_response(response: Value, executor: E) -> StdResult<Self, DecodingError> {
24 let map = value_to_map(response).map_err(|err| err.in_other("OK prepare response body"))?;
25 let value = find_and_take_single_key_in_map(keys::SQL_STMT_ID, map).ok_or_else(|| {
26 DecodingError::missing_key("SQL_STMT_ID").in_other("OK prepare response body")
27 })?;
28 let stmt_id: u64 = rmpv::ext::deserialize_from(value)
29 .map_err(|err| DecodingError::from(err).in_key("SQL_STMT_ID"))?;
30 Ok(Self::new(stmt_id, executor))
31 }
32
33 pub(crate) fn stmt_id(&self) -> u64 {
34 self.stmt_id
35 }
36}
37
38impl<E: Clone> Clone for PreparedSqlStatement<E> {
39 fn clone(&self) -> Self {
40 Self {
41 stmt_id: self.stmt_id,
42 executor: self.executor.clone(),
43 }
44 }
45}
46
47impl<E: Executor> PreparedSqlStatement<E> {
48 pub async fn execute<T>(&self, binds: T) -> Result<SqlResponse>
50 where
51 T: Tuple + Send,
52 {
53 Ok(SqlResponse(
54 self.executor
55 .send_request(Execute::new_statement_id(self.stmt_id, binds))
56 .await?,
57 ))
58 }
59}
60
61impl<E: Clone> PreparedSqlStatement<&E> {
62 pub fn with_cloned_executor(&self) -> PreparedSqlStatement<E> {
63 PreparedSqlStatement {
64 stmt_id: self.stmt_id,
65 executor: self.executor.clone(),
66 }
67 }
68}