tarantool_rs/client/sql/
response.rs

1use rmpv::Value;
2use serde::de::DeserializeOwned;
3
4use crate::{
5    codec::consts::keys,
6    errors::DecodingError,
7    utils::{extract_and_deserialize_iproto_data, find_and_take_single_key_in_map, value_to_map},
8};
9
10/// Response, returned from SQL requests.
11///
12/// Can be deserialized into different responses, depending on request.
13#[derive(Clone, Debug, PartialEq)]
14pub struct SqlResponse(pub(crate) rmpv::Value);
15
16impl SqlResponse {
17    /// Decode as response on `SELECT`.
18    pub fn decode_select<T>(self) -> Result<Vec<T>, DecodingError>
19    where
20        T: DeserializeOwned,
21    {
22        self.decode_data_vec()
23    }
24
25    // TODO: separate functions for PRAGMA and VALUES
26
27    /// Decode as data list in `IPROTO_DATA` tag.
28    ///
29    /// This is currently used for `SELECT`, `PRAGMA` and `VALUES` responses.
30    pub fn decode_data_vec<T>(self) -> Result<Vec<T>, DecodingError>
31    where
32        T: DeserializeOwned,
33    {
34        extract_and_deserialize_iproto_data(self.0)
35    }
36
37    fn decode_sql_info_raw(self) -> Result<Vec<(Value, Value)>, DecodingError> {
38        let map = value_to_map(self.0).map_err(|err| err.in_other("OK response body"))?;
39        find_and_take_single_key_in_map(keys::SQL_INFO, map)
40            .ok_or_else(|| DecodingError::missing_key("SQL_INFO"))
41            .and_then(value_to_map)
42            .map_err(|err| err.in_other("OK SQL response body"))
43    }
44
45    /// Get number of affected rows.
46    pub fn row_count(self) -> Result<u64, DecodingError> {
47        let sql_info = self.decode_sql_info_raw()?;
48        find_and_take_single_key_in_map(keys::SQL_INFO_ROW_COUNT, sql_info)
49            .ok_or_else(|| DecodingError::missing_key("SQL_INFO_ROW_COUNT"))
50            .and_then(|x| rmpv::ext::from_value(x).map_err(Into::into))
51    }
52}