tarantool_rs/client/sql/
prepared_statement.rs

1use 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    /// Execute prepared SQL query with parameters.
49    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}