Skip to main content

trino_rust_client/models/
error.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Deserialize, Serialize)]
6#[serde(rename_all = "camelCase")]
7pub struct QueryError {
8    pub message: String,
9    pub sql_state: Option<String>,
10    pub error_code: i32,
11    pub error_name: String,
12    pub error_type: String,
13    pub error_location: Option<ErrorLocation>,
14    #[serde(default)]
15    pub failure_info: Option<FailureInfo>,
16}
17
18/// A typed classification of the common Trino error names, so callers can
19/// match on well-known failures without comparing raw strings.
20///
21/// This intentionally covers only frequent cases; anything else is
22/// [`TrinoErrorKind::Other`] — use [`QueryError::error_name`] /
23/// [`QueryError::error_code`] for the full Trino error taxonomy.
24#[non_exhaustive]
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum TrinoErrorKind {
27    SyntaxError,
28    PermissionDenied,
29    UserCanceled,
30    CatalogNotFound,
31    SchemaNotFound,
32    SchemaAlreadyExists,
33    TableNotFound,
34    TableAlreadyExists,
35    ColumnNotFound,
36    ColumnAlreadyExists,
37    FunctionNotFound,
38    NotSupported,
39    /// Any other Trino error — inspect the raw `error_name` / `error_code`.
40    Other,
41}
42
43impl TrinoErrorKind {
44    fn from_name(error_name: &str) -> Self {
45        match error_name {
46            "SYNTAX_ERROR" => Self::SyntaxError,
47            "PERMISSION_DENIED" => Self::PermissionDenied,
48            "USER_CANCELED" => Self::UserCanceled,
49            "CATALOG_NOT_FOUND" => Self::CatalogNotFound,
50            "SCHEMA_NOT_FOUND" => Self::SchemaNotFound,
51            "SCHEMA_ALREADY_EXISTS" => Self::SchemaAlreadyExists,
52            "TABLE_NOT_FOUND" => Self::TableNotFound,
53            "TABLE_ALREADY_EXISTS" => Self::TableAlreadyExists,
54            "COLUMN_NOT_FOUND" => Self::ColumnNotFound,
55            "COLUMN_ALREADY_EXISTS" => Self::ColumnAlreadyExists,
56            "FUNCTION_NOT_FOUND" => Self::FunctionNotFound,
57            "NOT_SUPPORTED" => Self::NotSupported,
58            _ => Self::Other,
59        }
60    }
61}
62
63impl QueryError {
64    /// Classify this failure into a [`TrinoErrorKind`] for ergonomic matching
65    /// on the common Trino error names.
66    ///
67    /// ```
68    /// # use trino_rust_client::models::{QueryError, TrinoErrorKind};
69    /// # fn handle(err: &QueryError) {
70    /// match err.kind() {
71    ///     TrinoErrorKind::TableNotFound => { /* create it, retry, … */ }
72    ///     TrinoErrorKind::SyntaxError => { /* report err.message */ }
73    ///     _ => { /* fall back to err.error_name / err.error_code */ }
74    /// }
75    /// # }
76    /// ```
77    pub fn kind(&self) -> TrinoErrorKind {
78        TrinoErrorKind::from_name(&self.error_name)
79    }
80}
81
82#[derive(Debug, Deserialize, Serialize)]
83#[serde(rename_all = "camelCase")]
84pub struct ErrorLocation {
85    pub line_number: u32,
86    pub column_number: u32,
87}
88
89#[derive(Debug, Deserialize, Serialize)]
90#[serde(rename_all = "camelCase")]
91pub struct FailureInfo {
92    #[serde(rename = "type")]
93    pub ty: String,
94    pub suppressed: Vec<FailureInfo>,
95    pub stack: Vec<String>,
96    pub message: Option<String>,
97    pub cause: Option<Box<FailureInfo>>,
98    pub error_location: Option<ErrorLocation>,
99}
100
101impl fmt::Display for QueryError {
102    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103        writeln!(f, "message: {}", self.message)?;
104        if let Some(st) = &self.sql_state {
105            writeln!(f, "sql_state: {}", st)?;
106        }
107        writeln!(f, "error_code: {}", self.error_code)?;
108        writeln!(f, "error_type: {}", self.error_name)?;
109        if let Some(loc) = &self.error_location {
110            writeln!(f, "error_location: {}", loc)?;
111        }
112        if let Some(fi) = &self.failure_info {
113            writeln!(f, "failure_info: {}", fi)?;
114        }
115        Ok(())
116    }
117}
118
119impl std::error::Error for QueryError {}
120
121impl fmt::Display for ErrorLocation {
122    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123        write!(f, "({}, {})", self.line_number, self.column_number)
124    }
125}
126
127impl fmt::Display for FailureInfo {
128    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129        writeln!(f, "ty: {}", self.ty)?;
130        if let Some(msg) = &self.message {
131            writeln!(f, "message: {}", msg)?;
132        }
133        if let Some(loc) = &self.error_location {
134            writeln!(f, "loc: {}", loc)?;
135        }
136        writeln!(f, "stack:")?;
137        for s in &self.stack {
138            writeln!(f, "\ttype: {}", s)?;
139        }
140        if let Some(cause) = &self.cause {
141            writeln!(f, "cause: {}", cause)?;
142        }
143        Ok(())
144    }
145}
146
147#[cfg(test)]
148mod tests {
149    use super::*;
150
151    #[test]
152    fn test_loc() {
153        let loc = ErrorLocation {
154            line_number: 100,
155            column_number: 15,
156        };
157
158        assert_eq!("(100, 15)", format!("{}", loc));
159    }
160
161    #[test]
162    fn test_failure() {
163        let failure = FailureInfo {
164            ty: "xxxty".into(),
165            suppressed: vec![],
166            stack: vec!["stack_1".into(), "stack_2".into(), "stack_3".into()],
167            message: None,
168            cause: None,
169            error_location: None,
170        };
171
172        println!("{}", failure);
173    }
174
175    #[test]
176    fn test_error_kind() {
177        let mut err = QueryError {
178            message: "boom".into(),
179            sql_state: None,
180            error_code: 44,
181            error_name: "TABLE_NOT_FOUND".into(),
182            error_type: "USER_ERROR".into(),
183            error_location: None,
184            failure_info: None,
185        };
186        assert_eq!(err.kind(), TrinoErrorKind::TableNotFound);
187
188        err.error_name = "SOME_FUTURE_TRINO_ERROR".into();
189        assert_eq!(err.kind(), TrinoErrorKind::Other);
190    }
191}