odbc_api/handles/
sql_result.rs

1use odbc_sys::SqlReturn;
2
3/// Result of an ODBC function call. Variants hold the same meaning as the constants associated with
4/// [`SqlReturn`]. This type may hold results, but it is still the responsibility of the user to
5/// fetch and handle the diagnostics in case of an Error.
6#[derive(Debug, PartialEq, Eq, Clone, Copy)]
7pub enum SqlResult<T> {
8    /// The function has been executed successfully.
9    Success(T),
10    /// The function has been executed successfully. There have been warnings.
11    SuccessWithInfo(T),
12    /// Meaning depends on the function emitting `NoData`.
13    NoData,
14    /// Emmitted by execute in case delayed parameters have been bound and their input values are
15    /// now required.
16    NeedData,
17    /// The function was started asynchronously and is still executing.
18    StillExecuting,
19    /// The function returned an error state. Check diagnostics.
20    Error {
21        /// Name of the ODBC Api call which caused the error. This might help interpreting
22        /// associated ODBC diagnostics if the error is bubbled all the way up to the
23        /// end users output, but the context is lost.
24        function: &'static str,
25    },
26}
27
28impl SqlResult<()> {
29    /// Append a return value a successful to Result
30    pub fn on_success<F, T>(self, f: F) -> SqlResult<T>
31    where
32        F: FnOnce() -> T,
33    {
34        self.map(|()| f())
35    }
36}
37
38impl<T> SqlResult<T> {
39    /// `True` if variant is [`SqlResult::Error`].
40    pub fn is_err(&self) -> bool {
41        matches!(self, SqlResult::Error { .. })
42    }
43
44    /// Applies `f` to any value wrapped in `Success` or `SuccessWithInfo`.
45    pub fn map<U, F>(self, f: F) -> SqlResult<U>
46    where
47        F: FnOnce(T) -> U,
48    {
49        match self {
50            SqlResult::Success(v) => SqlResult::Success(f(v)),
51            SqlResult::SuccessWithInfo(v) => SqlResult::SuccessWithInfo(f(v)),
52            SqlResult::Error { function } => SqlResult::Error { function },
53            SqlResult::StillExecuting => SqlResult::StillExecuting,
54            SqlResult::NoData => SqlResult::NoData,
55            SqlResult::NeedData => SqlResult::NeedData,
56        }
57    }
58
59    pub fn unwrap(self) -> T {
60        match self {
61            SqlResult::Success(v) | SqlResult::SuccessWithInfo(v) => v,
62            _ => panic!("Invalid unwrapping of SqlResult"),
63        }
64    }
65}
66
67pub trait ExtSqlReturn {
68    fn into_sql_result(self, function_name: &'static str) -> SqlResult<()>;
69}
70
71impl ExtSqlReturn for SqlReturn {
72    fn into_sql_result(self, function: &'static str) -> SqlResult<()> {
73        match self {
74            SqlReturn::SUCCESS => SqlResult::Success(()),
75            SqlReturn::SUCCESS_WITH_INFO => SqlResult::SuccessWithInfo(()),
76            SqlReturn::ERROR => SqlResult::Error { function },
77            SqlReturn::NO_DATA => SqlResult::NoData,
78            SqlReturn::NEED_DATA => SqlResult::NeedData,
79            SqlReturn::STILL_EXECUTING => SqlResult::StillExecuting,
80            r => panic!("Unexpected return value '{r:?}' for ODBC function '{function}'"),
81        }
82    }
83}