tiberius/tds/codec/token/
token_error.rs

1use crate::{tds::codec::FeatureLevel, SqlReadBytes};
2use std::fmt;
3
4#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
5/// An error token returned from the server.
6pub struct TokenError {
7    /// ErrorCode
8    pub(crate) code: u32,
9    /// ErrorState (describing code)
10    pub(crate) state: u8,
11    /// The class (severity) of the error
12    pub(crate) class: u8,
13    /// The error message
14    pub(crate) message: String,
15    pub(crate) server: String,
16    pub(crate) procedure: String,
17    pub(crate) line: u32,
18}
19
20impl TokenError {
21    pub(crate) async fn decode<R>(src: &mut R) -> crate::Result<Self>
22    where
23        R: SqlReadBytes + Unpin,
24    {
25        let _length = src.read_u16_le().await? as usize;
26
27        let code = src.read_u32_le().await?;
28        let state = src.read_u8().await?;
29        let class = src.read_u8().await?;
30
31        let message = src.read_us_varchar().await?;
32        let server = src.read_b_varchar().await?;
33        let procedure = src.read_b_varchar().await?;
34
35        let line = if src.context().version() > FeatureLevel::SqlServer2005 {
36            src.read_u32_le().await?
37        } else {
38            src.read_u16_le().await? as u32
39        };
40
41        let token = TokenError {
42            code,
43            state,
44            class,
45            message,
46            server,
47            procedure,
48            line,
49        };
50
51        Ok(token)
52    }
53
54    /// The error code, see descriptions from [the manual].
55    ///
56    /// [the manual]: https://docs.microsoft.com/en-us/sql/relational-databases/errors-events/database-engine-events-and-errors?view=sql-server-ver15
57    pub fn code(&self) -> u32 {
58        self.code
59    }
60
61    /// The error state, used as a modifier to the error number.
62    pub fn state(&self) -> u8 {
63        self.state
64    }
65
66    /// The class (severity) of the error. A class of less than 10 indicates an
67    /// informational message.
68    pub fn class(&self) -> u8 {
69        self.class
70    }
71
72    /// The error message returned from the server.
73    pub fn message(&self) -> &str {
74        &self.message
75    }
76
77    /// The server name.
78    pub fn server(&self) -> &str {
79        &self.server
80    }
81
82    /// The name of the stored procedure causing the error.
83    pub fn procedure(&self) -> &str {
84        &self.procedure
85    }
86
87    /// The line number in the SQL batch or stored procedure that caused the
88    /// error. Line numbers begin at 1. If the line number is not applicable to
89    /// the message, the value is 0.
90    pub fn line(&self) -> u32 {
91        self.line
92    }
93}
94
95impl fmt::Display for TokenError {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        write!(
98            f,
99            "'{}' on server {} executing {} on line {} (code: {}, state: {}, class: {})",
100            self.message, self.server, self.procedure, self.line, self.code, self.state, self.class
101        )
102    }
103}