sqlint/connector/sqlite/
error.rs

1use crate::error::*;
2use libsqlite3_sys as ffi;
3use rusqlite::types::FromSqlError;
4
5impl From<rusqlite::Error> for Error {
6    fn from(e: rusqlite::Error) -> Error {
7        match e {
8            rusqlite::Error::ToSqlConversionFailure(error) => match error.downcast::<Error>() {
9                Ok(error) => *error,
10                Err(error) => {
11                    let mut builder = Error::builder(ErrorKind::QueryError(error));
12
13                    builder.set_original_message("Could not interpret parameters in an SQLite query.");
14
15                    builder.build()
16                }
17            },
18            rusqlite::Error::InvalidQuery => {
19                let mut builder = Error::builder(ErrorKind::QueryError(e.into()));
20
21                builder.set_original_message(
22                    "Could not interpret the query or its parameters. Check the syntax and parameter types.",
23                );
24
25                builder.build()
26            }
27            rusqlite::Error::ExecuteReturnedResults => {
28                let mut builder = Error::builder(ErrorKind::QueryError(e.into()));
29                builder.set_original_message("Execute returned results, which is not allowed in SQLite.");
30
31                builder.build()
32            }
33
34            rusqlite::Error::QueryReturnedNoRows => Error::builder(ErrorKind::NotFound).build(),
35
36            rusqlite::Error::SqliteFailure(
37                ffi::Error { code: ffi::ErrorCode::ConstraintViolation, extended_code: 2067 },
38                Some(description),
39            ) => {
40                let constraint = description
41                    .split(": ")
42                    .nth(1)
43                    .map(|s| s.split(", "))
44                    .map(|i| i.flat_map(|s| s.split('.').last()))
45                    .map(DatabaseConstraint::fields)
46                    .unwrap_or(DatabaseConstraint::CannotParse);
47
48                let kind = ErrorKind::UniqueConstraintViolation { constraint };
49                let mut builder = Error::builder(kind);
50
51                builder.set_original_code("2067");
52                builder.set_original_message(description);
53
54                builder.build()
55            }
56
57            rusqlite::Error::SqliteFailure(
58                ffi::Error { code: ffi::ErrorCode::ConstraintViolation, extended_code: 1555 },
59                Some(description),
60            ) => {
61                let constraint = description
62                    .split(": ")
63                    .nth(1)
64                    .map(|s| s.split(", "))
65                    .map(|i| i.flat_map(|s| s.split('.').last()))
66                    .map(DatabaseConstraint::fields)
67                    .unwrap_or(DatabaseConstraint::CannotParse);
68
69                let kind = ErrorKind::UniqueConstraintViolation { constraint };
70                let mut builder = Error::builder(kind);
71
72                builder.set_original_code("1555");
73                builder.set_original_message(description);
74
75                builder.build()
76            }
77
78            rusqlite::Error::SqliteFailure(
79                ffi::Error { code: ffi::ErrorCode::ConstraintViolation, extended_code: 1299 },
80                Some(description),
81            ) => {
82                let constraint = description
83                    .split(": ")
84                    .nth(1)
85                    .map(|s| s.split(", "))
86                    .map(|i| i.flat_map(|s| s.split('.').last()))
87                    .map(DatabaseConstraint::fields)
88                    .unwrap_or(DatabaseConstraint::CannotParse);
89
90                let kind = ErrorKind::NullConstraintViolation { constraint };
91                let mut builder = Error::builder(kind);
92
93                builder.set_original_code("1299");
94                builder.set_original_message(description);
95
96                builder.build()
97            }
98
99            rusqlite::Error::SqliteFailure(
100                ffi::Error { code: ffi::ErrorCode::ConstraintViolation, extended_code: 787 },
101                Some(description),
102            ) => {
103                let mut builder = Error::builder(ErrorKind::ForeignKeyConstraintViolation {
104                    constraint: DatabaseConstraint::ForeignKey,
105                });
106
107                builder.set_original_code("787");
108                builder.set_original_message(description);
109
110                builder.build()
111            }
112
113            rusqlite::Error::SqliteFailure(
114                ffi::Error { code: ffi::ErrorCode::ConstraintViolation, extended_code: 1811 },
115                Some(description),
116            ) => {
117                let mut builder = Error::builder(ErrorKind::ForeignKeyConstraintViolation {
118                    constraint: DatabaseConstraint::ForeignKey,
119                });
120
121                builder.set_original_code("1811");
122                builder.set_original_message(description);
123
124                builder.build()
125            }
126
127            rusqlite::Error::SqliteFailure(
128                ffi::Error { code: ffi::ErrorCode::DatabaseBusy, extended_code },
129                description,
130            ) => {
131                let mut builder = Error::builder(ErrorKind::SocketTimeout);
132                builder.set_original_code(format!("{extended_code}"));
133
134                if let Some(description) = description {
135                    builder.set_original_message(description);
136                }
137
138                builder.build()
139            }
140
141            rusqlite::Error::SqliteFailure(ffi::Error { extended_code, .. }, ref description) => match description {
142                Some(d) if d.starts_with("no such table") => {
143                    let table = d.split(": ").last().into();
144                    let kind = ErrorKind::TableDoesNotExist { table };
145
146                    let mut builder = Error::builder(kind);
147                    builder.set_original_code(format!("{extended_code}"));
148                    builder.set_original_message(d);
149
150                    builder.build()
151                }
152                Some(d) if d.contains("has no column named") => {
153                    let column = d.split(" has no column named ").last().into();
154                    let kind = ErrorKind::ColumnNotFound { column };
155
156                    let mut builder = Error::builder(kind);
157                    builder.set_original_code(format!("{extended_code}"));
158                    builder.set_original_message(d);
159
160                    builder.build()
161                }
162                Some(d) if d.starts_with("no such column: ") => {
163                    let column = d.split("no such column: ").last().into();
164                    let kind = ErrorKind::ColumnNotFound { column };
165
166                    let mut builder = Error::builder(kind);
167                    builder.set_original_code(format!("{extended_code}"));
168                    builder.set_original_message(d);
169
170                    builder.build()
171                }
172                _ => {
173                    let description = description.as_ref().map(|d| d.to_string());
174                    let mut builder = Error::builder(ErrorKind::QueryError(e.into()));
175                    builder.set_original_code(format!("{extended_code}"));
176
177                    if let Some(description) = description {
178                        builder.set_original_message(description);
179                    }
180
181                    builder.build()
182                }
183            },
184            e => Error::builder(ErrorKind::QueryError(e.into())).build(),
185        }
186    }
187}
188
189impl From<FromSqlError> for Error {
190    fn from(e: FromSqlError) -> Error {
191        Error::builder(ErrorKind::ColumnReadFailure(e.into())).build()
192    }
193}