odbc_safe/
diagnostics.rs

1use super::*;
2use sys::*;
3/// A buffer large enough to hold an `SOLState` for diagnostics and a terminating zero.
4pub type State = [SQLCHAR; SQL_SQLSTATE_SIZE + 1];
5
6/// Result of `Diagnostics::diagnostics`
7#[derive(Debug, Clone, Copy)]
8pub struct DiagResult {
9    /// A five-character SQLSTATE code (and terminating NULL) for the diagnostic record
10    /// `rec_number`. The first two characters indicate the class; the next three indicate the
11    /// subclass. For more information, see [SQLSTATE][1]s.
12    /// [1]: https://docs.microsoft.com/sql/odbc/reference/develop-app/sqlstates
13    pub state: State,
14    /// Native error code specific to the data source.
15    pub native_error: SQLINTEGER,
16    /// The total number of characters (excluding the terminating NULL) available to return in
17    /// `message_text`.
18    pub text_length: SQLSMALLINT,
19}
20
21/// A type implementing this trait is able to provide diagnostic information regarding the last
22/// method call.
23pub trait Diagnostics {
24    /// Returns the current values of multiple fields of a diagnostic record that contains error,
25    /// warning, and status information.
26    ///
27    /// # Arguments
28    ///
29    /// * `rec_number` - Indicates the status record from which the application seeks information.
30    ///                  Status records are numbered from 1.
31    /// * `message_text` - Buffer in which to return the diagnostic message text string. If the
32    ///                    number of characters to return is greater than the buffer length, the
33    ///                    diagnostic message is truncated to `max(message_text.len() - 1, 0)`. For
34    ///                    the format of the string, see [Diagnostic Messages][1]
35    ///
36    /// # Result
37    ///`
38    /// * `Success` - The function successfully returned diagnostic information.
39    /// * `Info` - The `message_text` buffer was too small to hold the requested diagnostic message.
40    ///            No diagnostic records were generated. To determine that a truncation occurred,
41    ///            the application must compare the buffer length to the actual number of bytes
42    ///            available, which is found in `DiagResult::text_length`
43    /// * `Error` - `rec_number` was negative or `0`.
44    /// * `NoData` - `rec_number` was greater than the number of diagnostic records that existed
45    ///              for the specified Handle. The function also returns `NoData` for any positive
46    ///              `rec_number` if there are no diagnostic records available.
47    /// [1]: https://docs.microsoft.com/sql/odbc/reference/develop-app/diagnostic-messages
48    fn diagnostics(
49        &self,
50        rec_number: SQLSMALLINT,
51        message_text: &mut [SQLCHAR],
52    ) -> ReturnOption<DiagResult>;
53}
54
55impl<H: Handle> Diagnostics for H {
56    fn diagnostics(
57        &self,
58        rec_number: SQLSMALLINT,
59        message_text: &mut [SQLCHAR],
60    ) -> ReturnOption<DiagResult> {
61        unsafe {
62            let mut text_length = 0;
63            let mut state = [0; 6];
64            let mut native_error = 0;
65            let ret = SQLGetDiagRec(
66                H::HANDLE_TYPE,
67                self.handle(),
68                rec_number,
69                state.as_mut_ptr(),
70                &mut native_error,
71                message_text.as_mut_ptr(),
72                message_text.buf_len(),
73                &mut text_length,
74            );
75            let result = DiagResult {
76                text_length: text_length,
77                state: state,
78                native_error: native_error,
79            };
80            match ret {
81                SQL_SUCCESS => ReturnOption::Success(result),
82                SQL_SUCCESS_WITH_INFO => ReturnOption::Info(result),
83                SQL_ERROR => ReturnOption::Error(()),
84                SQL_NO_DATA => ReturnOption::NoData(()),
85                unexpected => panic!("SQLGetDiagRec returned: {:?}", unexpected),
86            }
87        }
88    }
89}
90
91impl<S, E> Diagnostics for Return<S, E>
92where
93    S: Diagnostics,
94    E: Diagnostics,
95{
96    fn diagnostics(
97        &self,
98        rec_number: SQLSMALLINT,
99        message_text: &mut [SQLCHAR],
100    ) -> ReturnOption<DiagResult> {
101        match *self {
102            Success(ref s) | Info(ref s) => s.diagnostics(rec_number, message_text),
103            Error(ref e) => e.diagnostics(rec_number, message_text),
104        }
105    }
106}