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