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}